diff --git a/Dockerfile b/Dockerfile index 4de2d78..b2cc0bf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,6 +10,8 @@ RUN apt-get update && \ WORKDIR /opt/ddrv/src COPY src /opt/ddrv/src +COPY ./LICENSE /opt/ddrv/src/ + RUN npm config set @gov.nasa.jpl.m2020.cs3:registry=https://cae-artifactory.jpl.nasa.gov:443/artifactory/api/npm/npm-release-local/ RUN npm config set @gov.nasa.jpl.ammos.ids:registry=https://artifactory.jpl.nasa.gov/artifactory/api/npm/npm-develop-local/ diff --git a/Dockerfile-localbuild b/Dockerfile-localbuild index 590bbcf..c780c9c 100644 --- a/Dockerfile-localbuild +++ b/Dockerfile-localbuild @@ -9,6 +9,8 @@ RUN apt-get update && \ WORKDIR /opt/ddrv/src COPY src /opt/ddrv/src +COPY ./LICENSE /opt/ddrv/src/ + RUN npm config set @gov.nasa.jpl.m2020.cs3:registry=https://cae-artifactory.jpl.nasa.gov:443/artifactory/api/npm/npm-release-local/ RUN npm config set @gov.nasa.jpl.ammos.ids:registry=https://artifactory.jpl.nasa.gov/artifactory/api/npm/npm-develop-local/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..20f61d1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +COPYRIGHT + +Copyright (c) 2024 California Institute of Technology (“Caltech”). U.S. Government sponsorship acknowledged. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +Neither the name of Caltech nor its operating division, the Jet Propulsion Laboratory, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/Makefile b/Makefile index 806e6b4..f0d4d13 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,19 @@ export NAME ?= datadrive-commandline export RELEASE_NAME ?= latest +export VERSION ?= latest + install: npm --prefix src/ install package: - npm --prefix src/ run package + docker run --rm -v "${PWD}":"/opt/ddrv/":z -e "IN_DOCKER_CONTAINER=TRUE" -e "NAME=${NAME}" -e "VERSION=${VERSION}" -e "WORKING_DIR=/opt/ddrv" cae-artifactory.jpl.nasa.gov:17001/node:18.16.1 /opt/ddrv/ci.cd/create_zip.sh +push: + curl -H X-JFrog-Art-Api:${CAE_ARTI_TOKEN_PSW} -T deployment/dist/${NAME}__${VERSION}.zip ${ARTIFACTORY_URL}/${IMAGE_PREFIX}/${NAME}__${VERSION}.zip +copy: + docker run --rm -v "${PWD}":"/opt/ddrv/":z -e "IN_DOCKER_CONTAINER=TRUE" -e "NAME=${NAME}" -e "VERSION=${VERSION}" -e "NEW_TAG=${NEW_TAG}" -e "WORKING_DIR=/opt/ddrv" cae-artifactory.jpl.nasa.gov:17001/node:18.16.1 /opt/ddrv/ci.cd/copy_release.sh +clean: + docker run --rm -v "${PWD}":"/opt/ddrv/":z -e "IN_DOCKER_CONTAINER=TRUE" -e "NAME=${NAME}" -e "VERSION=${VERSION}" -e "WORKING_DIR=/opt/ddrv" cae-artifactory.jpl.nasa.gov:17001/node:18.16.1 /opt/ddrv/ci.cd/clean_dir.sh build: docker build -t $(NAME):$(RELEASE_NAME) -f Dockerfile-localbuild . @@ -16,7 +24,7 @@ test: npm --prefix src/ test release: - npm --prefix src/ run semantic-release + npm --prefix src/ install --only=dev && npm --prefix src/ run semantic-release release-dry-run: - npm --prefix src/ run semantic-release-dry-run \ No newline at end of file + npm --prefix src/ install --only=dev && npm --prefix src/ run semantic-release-dry-run \ No newline at end of file diff --git a/README.md b/README.md index 708773c..6e24b32 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ If you are a developer or want to make changes, or try an unreleased development #### Prerequisites -- NodeJS: tested with v14.15.0, versions newer should also work +- NodeJS: tested with v14.15.0, versions newer should also work. #### Building with Docker (recommended) @@ -56,8 +56,7 @@ If you are a developer or want to make changes, or try an unreleased development To configure the CLI, please run the following command: - `ddrv config --help` will show the help screen and available options -- The basic required configuration is the Datadrive Middleware server and the PEP server, -- ex: `./ddrv config -d [datadrive_middleware_hostname] -p [pep_hostname]` +- The basic required configuration is the Datadrive Middleware server and the PEP server, ex: `./ddrv config -d [datadrive_middleware_hostname] -p [pep_hostname]` - Other typical options include a custom log path and the time interval to roll the log files: `./ddrv config --dd-host datadrive-middle-dev.dev.m20.jpl.nasa.gov --pep-host data.dev.m20.jpl.nasa.gov --logdir log_output_folder --log-date-pattern daily` The command above will create a configuration JSON file in `~/.datadrive/datadrive.json`. Note: You should only need to run this once unless `~/.datadrive/datadrive.json` file is deleted or you are using the ddrv CLI with multiple environments. @@ -131,14 +130,15 @@ By default, logs are archived in a gzip file. To disable this functionality, set The `--log-date-pattern`, `--no_gzip_rolling_logs`, and `--logdir` options can also be used with the `ddrv subscribe` command to determine the logging options for that particular subscription session. -### Subscriptions with your own script +### Subscriptions that auto-execute a command on each downloaded file -You can run a single script that will be called for every notification. +You can run a single shell command that will be called for every file downloaded. You can use this to automatically run post-processing, for example. + +- Ex: `./ddrv subscribe -p [ocs_package_name] -o [output_directory_path_here] -r -x [regex_filter] --callback 'command_to_execute'` +- `--callback` flag's value should be in single quotes +- `--callback` flag's value is an shell command and can use these special variables: `$FILENAME` `$SRC_PATH` `$DEST_PATH` +- for example: `ddrv subscribe -if --retain-path -p sample-package -o output_folder -f 'filter-string*' -P --callback 'echo $FILENAME $SRC_PATH $DEST_PATH'` -- Ex: `./ddrv subscribe -p [ocs_package_name] -o [output_directory_path_here] -r -x [regex_filter] --plugin-path [path_to_script]` -- `--plugin-path` flag's value should be an absolute path to your script. -- Please the `src/plugin_examples` folder for example scripts that you can take inspiration from. -- You must inherit from `DdPlugin` class and implement `processItem` function. ## Unit Test @@ -289,7 +289,7 @@ Please note, these test cases are for **developers** performing manual test from #### Expected Results -- Files since given date will be downloaded. In this case, "seeme123.txt" should be downloaded. +- Files since given date will be downloaded. In this case, "seeme123.txt" should be downloaded.. #### Cleanup diff --git a/src/CHANGELOG.md b/src/CHANGELOG.md index 06d1d2b..00ea52c 100644 --- a/src/CHANGELOG.md +++ b/src/CHANGELOG.md @@ -1,3 +1,26 @@ +## [2.0.4](https://github.jpl.nasa.gov/MIPL/DataDrive-CommandLine/compare/v2.0.3...v2.0.4) (2024-10-09) + + +### Bug Fixes + +* release version to artifactory 2 ([#199](https://github.jpl.nasa.gov/MIPL/DataDrive-CommandLine/issues/199)) ([e5c2e80](https://github.jpl.nasa.gov/MIPL/DataDrive-CommandLine/commit/e5c2e8017975accbcdc13108e26f3c0cdc1848e3)) + +## [2.0.3](https://github.jpl.nasa.gov/MIPL/DataDrive-CommandLine/compare/v2.0.2...v2.0.3) (2024-10-09) + + +### Bug Fixes + +* push releaase version to artifactory ([#197](https://github.jpl.nasa.gov/MIPL/DataDrive-CommandLine/issues/197)) ([555a451](https://github.jpl.nasa.gov/MIPL/DataDrive-CommandLine/commit/555a451ee4b9b852065509e325affef9aefff1ff)) + +## [2.0.2](https://github.jpl.nasa.gov/MIPL/DataDrive-CommandLine/compare/v2.0.1...v2.0.2) (2024-10-09) + + +### Bug Fixes + +* Follow Notification Lambda approach to build and upload zip file + new way to clean directory ([#191](https://github.jpl.nasa.gov/MIPL/DataDrive-CommandLine/issues/191)) ([38cc89c](https://github.jpl.nasa.gov/MIPL/DataDrive-CommandLine/commit/38cc89c17e86a5f2601a008b0bd770b3d2941883)) +* still testing release stage ([#195](https://github.jpl.nasa.gov/MIPL/DataDrive-CommandLine/issues/195)) ([df295b8](https://github.jpl.nasa.gov/MIPL/DataDrive-CommandLine/commit/df295b8178930aef3c6243388d01af735987c627)) +* testing release ([#193](https://github.jpl.nasa.gov/MIPL/DataDrive-CommandLine/issues/193)) ([dca476e](https://github.jpl.nasa.gov/MIPL/DataDrive-CommandLine/commit/dca476e536157d904487dc08193620a6f218ee54)) + ## [2.0.1](https://github.jpl.nasa.gov/MIPL/DataDrive-CommandLine/compare/v2.0.0...v2.0.1) (2024-07-18) diff --git a/src/buildScript.js b/src/buildScript.js index 5e96108..d1f2907 100644 --- a/src/buildScript.js +++ b/src/buildScript.js @@ -1,29 +1,24 @@ -'use strict'; +"use strict"; -const shelljs = require('shelljs'); -const minimist = require('minimist'); -const fs = require('fs-extra'); -const path = require('path'); +const shelljs = require("shelljs"); +const minimist = require("minimist"); +const fs = require("fs-extra"); +const path = require("path"); const WORKSPACE = process.env.WORKSPACE || process.cwd(); const DIST_DIR = `${__dirname}-dist`; -const SVC_NAME = 'cli'; //path.basename(__dirname); +const SVC_NAME = "cli"; //path.basename(__dirname); const ZIP_FILE = `ddrv-${SVC_NAME}-bundle.zip`; -const DEPLOY_DIR = '../deployment'; -const PKG_DIR = './ddrv-cli'; +const DEPLOY_DIR = "../deployment"; +const PKG_DIR = "./ddrv-cli"; //console.log(`DIST_DIR = ${DIST_DIR}`) //console.log(`DEPLOY_DIR = ${DEPLOY_DIR}`) //console.log(`PKG_DIR = ${PKG_DIR}`) +const README_FILE = "README.TXT"; -const README_FILE = 'README.TXT'; - -const { - clean, - build, - deploy -} = minimist(process.argv.slice(2)); +const { clean, build, deploy } = minimist(process.argv.slice(2)); let logLevel = 0; @@ -32,11 +27,11 @@ function upLevel(lvlDelta) { } function log(msg) { - console.log(' '.repeat(logLevel) + msg); + console.log(" ".repeat(logLevel) + msg); } function err(msg) { - console.error(' '.repeat(logLevel) + msg); + console.error(" ".repeat(logLevel) + msg); } function doClean() { @@ -78,7 +73,11 @@ function doCopyRecursive(fromDir, toDir) { // Recurse if directory. const _stats = fs.lstatSync(fromFilePath); if (_stats.isDirectory()) { - if (files[i] === 'core' || files[i] === 'plugins' || files[i] === 'exceptions') { + if ( + files[i] === "core" || + files[i] === "plugins" || + files[i] === "exceptions" + ) { log(`Copying directory ${fromFilePath}...`); upLevel(1); doCopyRecursive(fromFilePath, toFilePath); @@ -88,7 +87,6 @@ function doCopyRecursive(fromDir, toDir) { log(`Copying file ${files[i]}`); fs.copySync(fromFilePath, toFilePath); } - } } @@ -110,7 +108,9 @@ function doCopy() { function doConfig() { log(`Setting up NPM config params in ${DIST_DIR}.`); if (process.env.VENUE || process.env.BRANCH) { - log(`Found environment variables VENUE=${process.env.VENUE} and BRANCH=${process.env.BRANCH}`); + log( + `Found environment variables VENUE=${process.env.VENUE} and BRANCH=${process.env.BRANCH}`, + ); const NPMRC = `${DIST_DIR}/.npmrc`; if (process.env.VENUE) { fs.writeFileSync(NPMRC, `venue = "${process.env.VENUE}"\n`); @@ -119,14 +119,35 @@ function doConfig() { fs.appendFileSync(NPMRC, `branch = "${process.env.BRANCH}"\n`); } } else { - log('No environment variables for VENUE/BRANCH. Deployment will use the defaults from package.json'); + log( + "No environment variables for VENUE/BRANCH. Deployment will use the defaults from package.json", + ); } } function doInstall() { log(`Running NPM INSTALL in ${DIST_DIR}.`); shelljs.cd(DIST_DIR); - shelljs.exec('npm install --production'); + shelljs.exec("npm install --production"); +} + +function doTextReplace() { + const licenseText = fs.readFileSync( + path.join(__dirname, "LICENSE"), + "utf-8", + ); + const licenseScript = fs.readFileSync( + path.join(DIST_DIR, "ddrv-license.js"), + "utf-8", + ); + const updatedLicenseScript = licenseScript.replace( + "${LICENSE_TEXT}", + licenseText, + ); + fs.writeFileSync( + path.join(DIST_DIR, "ddrv-license.js"), + updatedLicenseScript, + ); } function doBuild(clean = true) { @@ -134,6 +155,7 @@ function doBuild(clean = true) { upLevel(1); doInit(); doCopy(); + doTextReplace(); doConfig(); doInstall(); upLevel(-1); @@ -141,10 +163,12 @@ function doBuild(clean = true) { function doPackage() { shelljs.cd(DIST_DIR); - for (const tgtOS of ['linux', 'macos', 'win']) { + for (const tgtOS of ["linux", "macos", "win"]) { log(`Packaging the DataDrive CLI for ${tgtOS}`); fs.ensureDirSync(`${PKG_DIR}/${tgtOS}-x64`); - shelljs.exec(`pkg . -t ${tgtOS}-x64 --output ${PKG_DIR}/${tgtOS}-x64/ddrv`); + shelljs.exec( + `pkg . -t ${tgtOS}-x64 --output ${PKG_DIR}/${tgtOS}-x64/ddrv`, + ); shelljs.chmod(555, `${PKG_DIR}/${tgtOS}-x64/ddrv*`); } // Move the README @@ -153,7 +177,7 @@ function doPackage() { shelljs.cd(PKG_DIR); // ZIP it up, ready for staging. shelljs.exec(`zip -rq ${ZIP_FILE} .`); - shelljs.mv(`${ZIP_FILE}`, '..'); + shelljs.mv(`${ZIP_FILE}`, ".."); } function doStage() { @@ -190,10 +214,9 @@ function ensureProjectDir() { ensureProjectDir(); if (deploy) { doDeploy(); - //log(`Deploy option currently not supported`); + //log(`Deploy option currently not supported`); } else if (clean) { doClean(); } else if (build) { doBuild(); } - diff --git a/src/core/AxiosWrapper.js b/src/core/AxiosWrapper.js deleted file mode 100644 index 4def206..0000000 --- a/src/core/AxiosWrapper.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @author wphyo - * Created on 1/7/22. - */ -const axios = require('axios') - -class AxiosWrapper { - async request(options) { - try { - let result = await axios.request(options) - return result.data - } catch (e) { - // TODO better handling of axios exception - let err = new Error() - if (e['response'] === undefined) { - err.message = `No response key. ${e.toString()}` - err.statusCode = 503 - throw err - } - err.message = JSON.stringify(e.response.data) - err.statusCode = e.response.status - throw err - } - } - static builder() { - return new AxiosWrapper() - } -} -exports.AxiosWrapper = AxiosWrapper diff --git a/src/core/DataDriveMWServiceSettings.js b/src/core/DataDriveMWServiceSettings.js deleted file mode 100644 index ddbfe24..0000000 --- a/src/core/DataDriveMWServiceSettings.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @author wphyo - * Created on 6/1/22. - */ -const AxiosWrapper = require("./AxiosWrapper").AxiosWrapper; -const https = require("https"); -const DdUtils = require("./DdUtils"); -const DdLogger = require("./DdLogger").logger; - -class DataDriveMWServiceSettings { - constructor(ddHost, cssoToken) { - this._datadriveHost = ddHost; - this._cssoToken = cssoToken; - this._ocsVenue = null; - this._ocsUrl = null; - this._pepUrl = null; - } - - static builder(ddHost, cssoToken) { - return new DataDriveMWServiceSettings(ddHost, cssoToken); - } - - getOcsEndpointHost() { - return this._ocsUrl; - } - - getOcsApiStage() { - return this._ocsVenue; - } - - async loadSettings() { - const options = { - method: "GET", - url: `${this._datadriveHost}/`, - headers: { - Cookie: `ssosession=${this._cssoToken}`, - }, - httpsAgent: new https.Agent({ rejectUnauthorized: false }), - }; - try { - const ddSetting = await AxiosWrapper.builder().request(options); - this._ocsUrl = ddSetting["ocs_endpoint"]; - this._ocsVenue = ddSetting["ocs_stage"]; - DdLogger.debug( - "OCS Settings from DataDrive middleware [Url: " + - this._ocsUrl + - ", Stage: " + - this._ocsVenue + - "]", - ); - } catch (e) { - DdUtils.errorAndExit( - `Error occurred while querying DataDrive host for OCS settings. URL: "${options["url"]}" Status code: ${e.statusCode} Error: ${e.message}`, - ); - } - } -} - -exports.DataDriveMWServiceSettings = DataDriveMWServiceSettings; diff --git a/src/core/DdCliConfigFileIO.js b/src/core/DdCliConfigFileIO.js deleted file mode 100644 index 1168d95..0000000 --- a/src/core/DdCliConfigFileIO.js +++ /dev/null @@ -1,162 +0,0 @@ -/** - * @author wphyo - * Created on 1/8/22. - */ -'use strict'; - - -const DdUtils = require('./DdUtils.js'); -const jsonTryParse = require('../core/utils').jsonTryParse -const DdLogger = require('./DdLogger.js').logger; -const DdConstants = require('./DdConstants.js'); - - -//required for writing files synchronously -const fs = require('fs'); -const fse = require('fs-extra'); - -//Setup the env config using user home dir - -const DD_CFG_FILE = DdUtils.getDdCfgFilepath(); - -//Setup scripts to be called -const DD_CFG_SCRIPT = "dd-config"; - -let SINGLETON_INSTANCE = null - -class DdCliConfigFileIO { - constructor() { - if (SINGLETON_INSTANCE === null) { - this.__failOnError = true - this.__cachedConfig = null - SINGLETON_INSTANCE = this - } - return SINGLETON_INSTANCE - } - - setFailOnError(value) { - this.__failOnError = value - return this - } - - static builder() { - return new DdCliConfigFileIO() - } - - /** - * Tests for existence of DataDrive config file - * @return {boolean} - */ - ddCfgFileExists() { - return DdUtils.fileExists(DD_CFG_FILE) - } - - readConfig(failOnError = true) { - if (this.__cachedConfig !== null) { - return this.__cachedConfig - } - if (!this.ddCfgFileExists()) { - if (failOnError) { - DdUtils.errorAndExit(`ERROR reading the configuration file ${DD_CFG_FILE}.\nRun '${DD_CFG_SCRIPT}' to save a valid configuration.`); - } - return null - } - let fileData = null - try { - fileData = fs.readFileSync(DD_CFG_FILE, 'utf8') - } catch (e) { - if (e.code !== 'ENOENT') { - if (failOnError) { - DdUtils.errorAndExit(`ERROR reading the configuration file ${DD_CFG_FILE}.\n${e}`) - } else { - return null - } - } - } - - let tempConfig = jsonTryParse(fileData) - if (tempConfig['error'] !== undefined) { - if (failOnError) { - DdUtils.errorAndExit(`ERROR reading the configuration file ${DD_CFG_FILE}. Run '${DD_CFG_SCRIPT}' to save a valid configuration.`); - } else { - return null - } - } - tempConfig = tempConfig['result'] - - // Fill in missing values with NULLs. - if (!tempConfig.hasOwnProperty(DdConstants.PROP_DATADRIVE_HOST)) { - tempConfig[DdConstants.PROP_DATADRIVE_HOST] = null; - } - - if (!tempConfig.hasOwnProperty(DdConstants.PROP_PEP_HOST)) { - tempConfig[DdConstants.PROP_PEP_HOST] = null; - } - - this.__cachedConfig = tempConfig; - - return this.__cachedConfig; - } - - /** - * This only writes DataDrive specific configuration, ignoring - * anything that is for OCS. - */ - writeConfig(opt) { - //don't fail if file does not already exist, but check for null - let _cfg = this.readConfig(false); - if (!_cfg) { - _cfg = {}; - } - // Overwrite the current configuration with the supplied values. - if (opt.datadriveHost || opt.pepHost) { - if (opt.datadriveHost) { - _cfg[DdConstants.PROP_DATADRIVE_HOST] = opt.datadriveHost; - } - if (opt.pepHost) { - _cfg[DdConstants.PROP_PEP_HOST] = opt.pepHost; - } - } - // Write to the config file. - try { - console.log(DD_CFG_FILE, _cfg) - fse.outputFileSync(DD_CFG_FILE, JSON.stringify(_cfg, null, 2)) - } catch (error) { - DdUtils.errorAndExit(`Unable to write to the DataDrive configuration file ${DD_CFG_FILE}. Make sure that the path exists and that the directory is accessible to the logged in user.`) - } - this.__cachedConfig = _cfg - } - - getConfigValue(cfgName) { - let cfg = this.readConfig(this.__failOnError); - if (cfg[cfgName] !== undefined) { - return cfg[cfgName] - } - return null - } - - /** - * Get environment variable value - * @param {string} envName - */ - getEnvValue(envName) { - if (envName in process.env) { - return process.env[envName] - } - return null - } - - getDatadriveHost() { - return this.getEnvValue(DdConstants.ENV_DATADRIVE_HOST) || this.getConfigValue(DdConstants.PROP_DATADRIVE_HOST); - } - - getPepHost() { - return this.getEnvValue(DdConstants.ENV_PEP_HOST) || this.getConfigValue(DdConstants.PROP_PEP_HOST); - } - - getDebugEnabled() { - return this.getEnvValue(DdConstants.ENV_DEBUG_ENABLED) || this.getConfigValue(DdConstants.PROP_DEBUG_ENABLED); - } -} - -exports.DdCliConfigFileIO = DdCliConfigFileIO diff --git a/src/core/DdConfig.js b/src/core/DdConfig.js deleted file mode 100644 index 055723e..0000000 --- a/src/core/DdConfig.js +++ /dev/null @@ -1,173 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const globToRegExp = require('glob-to-regexp'); -const DdConsts = require('./DdConstants.js'); -const SsoToken = require('./SsoToken.js'); -const DdUtils = require('./DdUtils.js'); -const DdLogger = require('./DdLogger.js').logger; -const {DdCliConfigFileIO} = require('./DdCliConfigFileIO'); -const OcsUtils = require('./OcsUtils.js'); -//OCS library -const OCS = require('@gov.nasa.jpl.m2020.cs3/ocs-js-client'); - -/** - * Definition of the DataDrive Web Socket client - * - * @type {DdConfig} - */ -class DdConfig { - /** - * @constructor - * @param {object} program - Command object from Commander library - * @param {boolean} load_config - Default: true; load configs such as hostnames and csso token; not loading config is used for unit tests - */ - constructor(program, load_config=true) { - this.ocsUtils = null - //lets assume the worst case... - this.wasConfiguredSuccessfully = false; - this.ssoTokenApi = undefined; - this.cssoToken = undefined; - this.datadriveHost = undefined; - this.pepUrl = undefined; - this.ocsHost = undefined; - this.ocsAPIDeployment = undefined; - - if (load_config) { - let ddHost = DdCliConfigFileIO.builder().getDatadriveHost(); - - if (! ddHost) { - DdLogger.error('Missing required configuration: '+DdConsts.PROP_DATADRIVE_HOST); - DdLogger.error('Please check your configuration via the "dd-config" command.'); - return null; - } - let pepHost = DdCliConfigFileIO.builder().getPepHost(); - if (! pepHost) { - DdLogger.error('Missing required configuration: '+DdConsts.PROP_PEP_HOST); - DdLogger.error('Please check your configuration via the "dd-config" command.'); - return null; - } - - this.datadriveHost = "https://" + ddHost; - this.pepUrl = "https://" + pepHost; - - //Check the environment for the DEBUG state - let debugEnvVal = DdCliConfigFileIO.builder().getDebugEnabled(); - if (DdUtils.isValueTrue(debugEnvVal)) - { - DdLogger.setDebugEnabled(true); - } - - //CSSO token - this.ssoTokenApi = new SsoToken(); - let token = this.ssoTokenApi.getToken(); - if (DdUtils.isEmptyOrNullString(token)) - { - throw Error(`Could not load CSSO credentials/token.`); - } - this.cssoToken = token; - } - }; - - getPepUrl() { - return this.pepUrl - } - - getDatadriveHost() { - return this.datadriveHost - } - - getOcsHost() { - return this.ocsHost - } - - getOcsUtils() { - return this.ocsUtils - } - - //--------------------------------------------------------------------- - - setOcsSettings(host, venue) { - this.ocsHost = host; - this.ocsAPIDeployment = venue; - }; - - //--------------------------------------------------------------------- - - getCssoToken() { - return this.cssoToken; - }; - - getUserNameFromCssoToken() { - // Ex: ::<32 random characters> - const splits = this.cssoToken.split(":"); - return splits[1]; - } - - reloadCssoToken() { - this.ssoTokenApi.loadToken(); - let newToken = this.ssoTokenApi.getToken(); - if (newToken === this.cssoToken) { - DdLogger.info("CSSO token has not changed, NOT reloading..."); - return false - } - DdLogger.info("CSSO token has changed, reloading..."); - this.cssoToken = newToken; - return true - } - - /** - * Reload the CSSO Token from .cssotoken folder if ths token is about to expire; default is 1 hour before expiration - * Note: This actually DOES NOT renew the token for you, unfortunately, right now you have to do that seperately via a cron job. - * Note: This function also does not reconnect the websocket; this function will return true or false to denote whether or not - * csso token has been reloaded. - */ - reloadIfSSOTokenAboutToExpire() { - if (this.ssoTokenApi.isTokenAboutToExpired()) { - DdLogger.info("Attempting to reload CSSO token from 'ssosession' file because it is about to expire."); - return this.reloadCssoToken(); - } - return false; - } - - //--------------------------------------------------------------------- - - isConfigured() { - return this.wasConfiguredSuccessfully; - } - - configured() { - this.wasConfiguredSuccessfully = true; - } - - //--------------------------------------------------------------------- - - /** - * Create OCS client object based on ocsHost and ocsAPIDeployment - */ - createOcsClient() - { - //CREATE OCS CLIENT - let ocsConfig = { - ocsEndpointHost: this.ocsHost, - ocsApiStage: this.ocsAPIDeployment - }; - - let ocsClient = new OCS(ocsConfig); - return ocsClient; - } - - /** - * Initialize OCS client and ocsUtils class - */ - initiate_OcsClient() - { - - //create an OCS client - this.ocsClient = this.createOcsClient(); - - //create an OCS utils layer - this.ocsUtils = OcsUtils.builder(this.ocsClient, this.cssoToken) - } -} - -module.exports = DdConfig; diff --git a/src/core/DdConstants.js b/src/core/DdConstants.js index 4179df1..3f85ab9 100644 --- a/src/core/DdConstants.js +++ b/src/core/DdConstants.js @@ -37,7 +37,7 @@ const ENV_DEBUG_ENABLED = "DEBUG"; const DEFAULT_DD_HOST = "datadrive-mid.m20-dev.jpl.nasa.gov"; const DEFAULT_PEP_HOST = "data.m20-dev.jpl.nasa.gov"; const DEFAULT_LOG_PATH = "./"; -const DEFAULT_VENUE = "M20"; +const DEFAULT_AUTH_TYPE = "M20"; //OCS configuration const PROP_OCS_HOST = "ocsEndpointHost"; @@ -95,7 +95,7 @@ module.exports = { S3_URL_REGEX, DEFAULT_LOG_PATH, SSO_SESSION_KEY_LOOKUP, - DEFAULT_VENUE, + DEFAULT_AUTH_TYPE, SSO_KEY_LOOKUP, //DATADRIVE_HOST }; diff --git a/src/core/DdDirectoryListener.js b/src/core/DdDirectoryListener.js deleted file mode 100644 index e3b4fa3..0000000 --- a/src/core/DdDirectoryListener.js +++ /dev/null @@ -1,144 +0,0 @@ - -//Libraries -const fs = require('fs'); -const os = require('os'); -const path = require('path'); -const chokidar = require('chokidar'); - -//Local imports -const DdLogger = require('./DdLogger.js').logger; -const DdUtils = require('./DdUtils.js'); -const DdPubConfig = require('./DdPubConfig.js'); - - - -let DdDirectoryListener = (function () { - - - //--------------------------------------------------------------------- - - /** - * Constructor. - * - * @constructor - */ - let DdDirectoryListener = function (pubConfig) { - this._config = pubConfig; - - this._directory = path.resolve(this._config.sourceDir); - - this._eventCallback = null; - this._errorCallback = null; - - this._watcher = null; - - }; - - - //--------------------------------------------------------------------- - - DdDirectoryListener.prototype.setMessageCallback = function(cb) { - this._eventCallback = cb; - }; - - //--------------------------------------------------------------------- - - DdDirectoryListener.prototype.setErrorCallback = function(cb) { - this._errorCallback = cb; - }; - - //--------------------------------------------------------------------- - - DdDirectoryListener.prototype.startSession = function() { - this.listen(); - }; - - //--------------------------------------------------------------------- - - DdDirectoryListener.prototype.isActive = function() { - return (null != this._watcher); - }; - - //--------------------------------------------------------------------- - - DdDirectoryListener.prototype.getDirectory = function() { - return this._directory; - }; - - - //--------------------------------------------------------------------- - - - - DdDirectoryListener.prototype.listen = function(url) { - - if (this._watcher) { - return; - } - - let that = this; - - this._watcher = chokidar.watch(this._directory, { - ignored: /[\/\\]\./, - persistent: true, - ignoreInitial: true - }); - - if (this._watcher) { - this._watcher.on('add', function (path) { - that.handleNewFileEvent(path, false); - }); - this._watcher.on('change', function (path) { - that.handleNewFileEvent(path, true); - }); - } - }; - - //--------------------------------------------------------------------- - - DdDirectoryListener.prototype.handleNewFileEvent = function(filepath, changeFlag) { - - if (DdUtils.isEmptyOrNullString(filepath)) { - return; - } - - - let fullpath = filepath; - if (! path.isAbsolute(fullpath)) { - fullpath = path.join(this._directory, filepath); - } - - - if (!this._config.satisfiesFilter(filepath)) { - return; - } - - - if (this._eventCallback) { - this._eventCallback(fullpath, changeFlag); - } - }; - - //--------------------------------------------------------------------- - - //--------------------------------------------------------------------- - //--------------------------------------------------------------------- - - //Stops the token refresh timer. - DdDirectoryListener.prototype.cancel = function() { - - //cleanup - if (this._watcher) - { - this._watcher.close(); - this._watcher = null; - } - }; - - //--------------------------------------------------------------------- - - return DdDirectoryListener; - -}()); - -module.exports = DdDirectoryListener; diff --git a/src/core/DdError.js b/src/core/DdError.js deleted file mode 100644 index 4a169d7..0000000 --- a/src/core/DdError.js +++ /dev/null @@ -1,22 +0,0 @@ -class QueueEmptyError extends Error { - constructor(message) { - super(message); - } -} -class MaxProcessSizeError extends Error { - constructor(message) { - super(message); - } -} - -class CannotWriteToLocalFileError extends Error { - constructor(message) { - super(message); - } -} - -module.exports = { - "QueueEmptyError": QueueEmptyError, - "MaxProcessSizeError": MaxProcessSizeError, - "CannotWriteToLocalFileError": CannotWriteToLocalFileError -}; \ No newline at end of file diff --git a/src/core/DdFileMetadata.js b/src/core/DdFileMetadata.js deleted file mode 100644 index d0f97c8..0000000 --- a/src/core/DdFileMetadata.js +++ /dev/null @@ -1,96 +0,0 @@ -const moment = require('moment'); -const DdConsts = require('./DdConstants.js'); - -/** - * @typedef {Object} OCSPathObj - * @property {string} ocs_path - * @property {string} ocs_name - */ - -/** - * Splits ocs_full_name into ocs_path and ocs_name - * Ex: /jeff/Slowpoke.gif to "/jeff" and "Slowpoke.gif" - * @param {string} ocs_full_name - * @returns {OCSPathObj} - */ -function getOCSPathObj(ocs_full_name) { - let splits = ocs_full_name.split("/"); - let ocs_name = splits[splits.length - 1]; - let ocs_path_end_index = ocs_full_name.indexOf(ocs_name) - 1; - let ocs_path = ocs_full_name.substring(0, ocs_path_end_index); - return {'ocs_name': ocs_name, 'ocs_path': ocs_path}; -} - -class FileMetadata { - constructor() { - /** @type {Date} */ - this.ocs_updated_at = undefined; - /** @type {string} */ - this.ocs_full_name = undefined; - /** @type {string} */ - this.ocs_dataset_id = undefined; - /** @type {string} */ - this.ocs_package_id = undefined; - /** @type {string} */ - this.ocs_url = undefined; - /** @type {string} */ - this.ocs_path = undefined; - this.ocs_name = undefined; - /** @type {string} */ - this.ocs_owner = undefined; - /** @type {string} */ - this.download_url = undefined; - /** @type {string} */ - this.event_type = undefined; - } - - getOcsUpdatedAt() { - return this.ocs_updated_at - } - - getOcsName() { - return this.ocs_name - } - - /** - * Converts JSON object into FileMetadata object that is common amongst events - * @param {object} json - */ - unmarshall(json) { - this.ocs_full_name = json.ocs_full_name; - this.ocs_url = json.ocs_url; - this.download_url = json.ocs_download_url; - this.getOCSPathObj = getOCSPathObj(this.ocs_full_name); - this.ocs_path = this.getOCSPathObj.ocs_path; - this.ocs_name = this.getOCSPathObj.ocs_name; - } - - /** - * Converts OCS event JSON object into FileMetadata object; this is to make type checking easier during development - * @param {object} json - */ - unmarshallOCS(json) { - this.unmarshall(json); - this.ocs_updated_at = json.package_dataset_event_time ? moment(json.package_dataset_event_time).toDate() : undefined; - this.ocs_dataset_id = json.dataset_id; - this.ocs_package_id = json.package_id; - this.event_type = DdConsts.EVENTTYPE_OCS; - } - - /** - * Converts DataDrive PLAYBACK event JSON object into FileMetadata object; this is to make type checking easier during development - * @param {object} json - */ - unmarshallPlayback(json) { - this.unmarshall(json); - this.ocs_updated_at = json.ocs_updated_at ? moment(json.ocs_updated_at).toDate() : undefined; - this.ocs_dataset_id = json.ocs_dataset_id; - this.ocs_package_id = json.ocs_package_id; - this.ocs_owner = json.ocs_owner; - this.event_type = DdConsts.EVENTTYPE_PLAYBACK; - } -} - -module.exports = { - "FileMetadata": FileMetadata -}; diff --git a/src/core/DdLogger.js b/src/core/DdLogger.js index c2b7712..cfea1c9 100644 --- a/src/core/DdLogger.js +++ b/src/core/DdLogger.js @@ -72,7 +72,7 @@ if (config.logDatePattern) { } const logger = winston.createLogger({ - level: "debug", + level: "info", format: combine( label({ label: "DataDrive" }), timestamp(), @@ -167,4 +167,13 @@ exports.logger = { logger.error(_msg); } }, + errorAndExit: function (err) { + if (err instanceof Error) { + logger.error(err.message); + logger.debug(err.stack); + } else { + logger.error(err); + } + process.exit(1); + }, }; diff --git a/src/core/DdOptions.js b/src/core/DdOptions.js deleted file mode 100644 index b414814..0000000 --- a/src/core/DdOptions.js +++ /dev/null @@ -1,270 +0,0 @@ -"use strict"; - -const os = require("os"); -const HOME = os.homedir(); -const path = require("path"); -const fs = require("fs"); - -const prog = require("commander"); -const Client = require("@gov.nasa.jpl.m2020.cs3/ocs-js-client"); -const DdConsts = require("./DdConstants.js"); - -let options = (function () { - let parsed = false; - - let options = function () { - parsed = false; - }; - - // Make module-local variables visible. - options.program = prog; - - //-------------------------------------------------------------------------- - // Mirror API of commander. - //-------------------------------------------------------------------------- - - options.version = function (...args) { - prog.version(...args); - }; - - options.option = function (...args) { - prog.option(...args); - }; - - options.parseTopArgs = function (...args) { - options.parseInternal(false, ...args); - }; - - options.parse = function (...args) { - options.setName(); - options.parseInternal(true, ...args); - }; - - options.parseInternal = function (addStandard, ...args) { - if (parsed) { - throw Error("You can only call parse() once."); - } - // Add the standard options. - if (addStandard) { - addStandardOptions(); - } - - // Add the standard help if not already done. - //if (typeof prog._events['--help'] === 'undefined') { - prog.on("--help", printStandardHelp); - //} - - // Parse. - try { - prog.parse(...args); - parsed = true; - } catch (err) { - options.errorAndExit(err); - } - validateArgs(prog); - }; - - options.command = function (...args) { - prog.command(...args); - }; - - options.usage = function (...args) { - prog.usage(...args); - }; - - options.setArgs = function (...args) { - prog.arguments(...args); - }; - - options.setName = function () { - let cmdName = path.basename(require.main.filename); - cmdName = cmdName.replace(/^([^-]+)-([^.]+)\.js/, "$1-$2"); - prog.name(cmdName); - }; - - //-------------------------------------------------------------------------- - // Value added methods. - //-------------------------------------------------------------------------- - - options.setCustomHelp = function (printCustomHelp) { - if (parsed) { - throw Error("Cannot call setCustomHelp after calling parse"); - } - prog.on("--help", function () { - printCustomHelp(); - //printStandardHelp(); - }); - }; - - options.errorAndExit = function (err) { - printErrMessage(err); - process.exit(1); - }; - - options.exit = function (exitCode) { - process.exit(exitCode); - }; - - /** - * - * @param {string[]} args - */ - options.parseSubscriptionOptions = function (args) { - //DdOptions.setArgs('[FILE...]', 'The files or expressions to list.'); - - this.version("\n*** " + DdConsts.CLIENT_TITLE + " ***\n\n"); - this.option( - "-p, --package-name [pkg name]", - "The name of the package.", - ); - this.option("-o, --output-dir ", "The output directory."); - this.option( - "-f, --filter [value]", - "A wildcard expression to filter files based on OCS Full Name.", - "*", - ); - this.option( - "-x, --regex [value]", - "A regex expression to filter files based on OCS Full Name. Please reference https://www.elastic.co/guide/en/elasticsearch/reference/6.4/query-dsl-regexp-query.html#regexp-syntax and NodeJS RegExp.", - ); - this.option( - "-s, --saved-search-name [value]", - "Name of your personnel saved search.", - ); - this.option( - "-r, --retain-path", - "Use the S3 path as relative path when writing files", - ); - this.option( - "-P, --playback", - "Get events that has since happened after the last downloaded file.", - ); - this.option( - "-if, --include-full-path", - "If filter and regex expressions include only the name or the full path. defaulted to `NO`.", - ); - this.option( - "-O, --overwrite", - "Overwrite file if it already exists in that path.", - ); - this.option( - "-S, --skip-unchanged", - "Only download files that are new or have changed.", - ); - // DdOptions.option('--pluginsAsync', 'Execute custom plugins asynchronously, this will be ignored if plugins are not enabled.'); - // this.option('--pluginsDir [plugin dir]', 'Directory to load custom plugins.'); - this.option( - "--plugin-path [value]", - "Path to the custom plugin file that implements class DdPlugin.", - ); - this.option( - "--disable-download", - "Disable downloading of files. Make sure to still include an output-dir option.", - ); - //DdOptions.parseTopArgs(process.argv); - // Utils.setCustomHelp(function () { - // console.log(''); - // console.log(' You can use the * and ? wildcards in FILE, as well as [].'); - // }); - - this.parse(args); - }; - - //-------------------------------------------------------------------------- - // Internal methods. - //-------------------------------------------------------------------------- - - const validateArgs = function () { - let _msg = ""; - prog.options.forEach(function (opt) { - // if (opt.required !== 0 || opt.required === true) { - if (opt.required === true) { - let _name = optName(opt.long); - // console.log("DEBUG::Opt.required? = "+_name+" = "+opt.required); - if (!prog[_name]) { - _msg = _msg + `ERROR: ${opt.flags} is required.\n`; - } - } - }); - if (_msg !== "") { - options.errorAndExit(_msg); - } - }; - - let optName = function (longFlag) { - let _name = longFlag.replace("--", ""); - return _name.split("-").reduce(function (str, word) { - return str + word[0].toUpperCase() + word.slice(1); - }); - }; - - let printStandardHelp = function () { - console.log(""); - console.log( - ' NOTE that you have to specify flags separately ("-p -d" and NOT "-pd").', - ); - console.log(""); - // console.log(' For a full explanation of all options, consult the online documentation'); - // console.log(' at https://github.jpl.nasa.gov/M2020-CS3/m2020-data-lake/wiki/OCS-CLI-Reference'); - }; - - let addStandardOptions = function () { - prog.option( - "-q, --quiet", - "If specified, do not output progress messages", - false, - ); - }; - - let printErrMessage = function (...args) { - if (args.length > 1) { - console.error(...args); - } else { - let err = args[0]; - let _msg; - if (err instanceof Error) { - _msg = `error: ${err.toString()}`; - } else if (typeof err === "object") { - if (err.Message) { - _msg = `error: ${err.Message}`; - } else if (err.message) { - _msg = `error: ${err.message}`; - } else if (err.reason) { - _msg = `error: ${err.reason}\n ${err.exception}`; - } else { - _msg = JSON.stringify(err, null, 2); - } - } else { - if ( - err.toString().startsWith("ERROR") || - err.toString().startsWith("error") - ) { - _msg = err; - } else { - _msg = `error: ${err.toString()}`; - } - } - - // Add causes, if any - if (err.causes) { - _msg = `${_msg}\nCaused By:`; - for (let c of err.causes) { - if (c.message) { - _msg = `${_msg}\n${c.message}`; - } else if (c.error.message) { - _msg = `${_msg}\n${c.error.message}`; - } else { - _msg = `${_msg}\n${c}`; - } - } - } - - console.error(""); - console.error(_msg); - } - }; - - return options; -})(); - -module.exports = options; diff --git a/src/core/DdPlugin.js b/src/core/DdPlugin.js deleted file mode 100644 index 454abcb..0000000 --- a/src/core/DdPlugin.js +++ /dev/null @@ -1,10 +0,0 @@ -class Plugin { - constructor() { - - } - - async processItem(item) { - } -} - -module.exports = Plugin; \ No newline at end of file diff --git a/src/core/DdPluginHandler.js b/src/core/DdPluginHandler.js deleted file mode 100644 index a763bab..0000000 --- a/src/core/DdPluginHandler.js +++ /dev/null @@ -1,135 +0,0 @@ -const { FileMetadata } = require('./DdFileMetadata.js'); -const fs = require('fs'); -const path = require('path'); -const DdLogger = require('./DdLogger.js').logger; -const DdSubConfig = require('./DdSubConfig'); -const DdPlugin = require('./DdPlugin.js'); -const DdUtils = require('./DdUtils.js'); -const _ = require('lodash'); - - -class PluginHandler { - /** - * Fires a single plugin. - * @param {DdSubConfig} config - */ - constructor(config) { - this.dict = {}; - this.config = config; - // Default plugins directory - if (!this.config.disableDownload) { - this.dict['FileDownloader'] = require('../plugins/FileDownloaderPlugin.js'); - } - // Custom plugins directory - if (this.config.pluginPath) { - this.dict['CustomPlugin'] = load_plugin(DdUtils.ensureAbsolutePath(this.config.pluginPath)); - } - } - - /** - * If plugin option is enabled, call every plugins in "plugins" folder's "processItem" function - * @param {FileMetadata} metadata - */ - async callProcessItem(metadata) { - for (let key in this.dict) { - try { - let config = _.cloneDeep(this.config); // Objects in JS is pass by reference; deep copy config so plugins cannot mess with upper level DdSubConfig class - let plug = new this.dict[key](config); - DdLogger.debug(`calling ${key}`); - await plug.processItem(metadata); - DdLogger.debug(`called ${key}`); - } catch (error) { - DdLogger.error(`An error occurred when invoking function processItem for ${key}`); - DdLogger.error(error.message); - DdLogger.debug(error.stack); - } - } - // await Promise.all(result); - } - // TODO: Look into adding checks to ensure each plugin is correct -} - -class MultiPluginHandler { - /** - * Fires plugins synchronously based on a given folder; Currently runs them randomly, need ordering if this eventually becomes a production feature. - * @param {DdSubConfig} config - */ - constructor(config) { - this.dict = {}; - this.config = config; - // Default plugins directory - // load_plugins(this.dict, path.join(process.cwd(), 'plugins')); - if (!this.config.disableDownload) { - this.dict['FileDownloader'] = load_plugin(path.join(process.cwd(), 'plugins', 'FileDownloaderPlugin.js')); - } - // Custom plugins directory - if (this.config.pluginsDir) { - load_plugins(this.dict, DdUtils.ensureAbsolutePath(this.config.pluginsDir)); - } - } - - /** - * If plugin option is enabled, call every plugins in "plugins" folder's "processItem" function - * @param {FileMetadata} metadata - */ - async callProcessItem(metadata) { - // let result = [] - for (let key in this.dict) { - try { - let config = _.cloneDeep(this.config); // Objects in JS is pass by reference; deep copy config so plugins cannot mess with upper level DdSubConfig class - let plug = new this.dict[key](config); - DdLogger.debug(`calling ${key}`); - await plug.processItem(metadata); - DdLogger.debug(`called ${key}`); - // result.push(plug.processItem(metadata)); - } catch (error) { - DdLogger.error(`An error occurred when invoking function processItem for ${key}`); - DdLogger.error(error); - } - } - // await Promise.all(result); - } - // TODO: Look into adding checks to ensure each plugin is correct -} - -/** - * @param {string} pluginPath - */ -let load_plugin = (pluginPath) => { - try { - let cls = require(pluginPath); - if (cls.prototype instanceof DdPlugin) { - return cls; - } - else { - throw new Error(`Plugin does not inherit from Plugin class.`); - } - } catch (error) { - DdUtils.errorAndExit(error); - } -}; - -/** - * @param {Object} dict - */ -let load_plugins = (dict, pluginsDir) => { - try { - let plugins = fs.readdirSync(pluginsDir); - for (let plugin of plugins) { - let cls = require(path.join(pluginsDir, plugin)); - if (cls.prototype instanceof DdPlugin) { - dict[plugin] = cls - } - else { - throw new Error(`Plugin ${plugin} does not inherit from Plugin class.`); - } - } - } catch (error) { - DdUtils.errorAndExit(error); - } -}; - -module.exports = { - 'PluginHandler': PluginHandler, - 'MultiPluginHandler': MultiPluginHandler, -}; \ No newline at end of file diff --git a/src/core/DdPubConfig.js b/src/core/DdPubConfig.js deleted file mode 100644 index 4c54614..0000000 --- a/src/core/DdPubConfig.js +++ /dev/null @@ -1,329 +0,0 @@ -const fs = require('fs'); -const os = require('os'); -const path = require('path'); -const upath = require('upath'); -//const argv = require('argv-parse'); -const globToRegExp = require('glob-to-regexp'); - - - -const DdConsts = require('./DdConstants.js'); -const SsoToken = require('./SsoToken.js'); -const DdUtils = require('./DdUtils.js'); -const DdLogger = require('./DdLogger.js').logger; -const {DdCliConfigFileIO} = require('./DdCliConfigFileIO'); - -/** - * Definition of the DataDrive Web Socket client - * - * @type {DdPubConfig} - */ -let DdPubConfig = (function () { - - - /** - * @constructor - */ - let DdPubConfig = function (program) { - - //lets assume the worst case... - this.wasConfiguredSuccessfully = false; - - //----------------- - - let ddHost = DdCliConfigFileIO.builder().getDatadriveHost(); - - if (! ddHost) { - DdLogger.error('Missing required configuration: '+DdConsts.PROP_DATADRIVE_HOST); - DdLogger.error('Please check your configuration via the "dd-config" command.'); - return null; - } - - this.datadriveHost = "https://"+ddHost; - this.ocsHost = null; - this.ocsAPIDeployment = null; - - //Check the environment for the DEBUG state - let debugEnvVal = DdCliConfigFileIO.builder().getConfigValue(DdConsts.PROP_DEBUG_ENABLED); - if (DdUtils.isValueTrue(debugEnvVal)) - { - DdLogger.setDebugEnabled(true); - } - - - //----------------- - - //CSSO token - this.ssoTokenApi = new SsoToken(); - let token = this.ssoTokenApi.getToken(); - if (DdUtils.isEmptyOrNullString(token)) - { - throw Error(`Could not load CSSO credentials/token.`); - } - this.cssoToken = token; - - - - this.packageId = null; - this.packageName = null; - this.packageBucket = null; - this.retainPath = false; - this.overwriteEnabled = false; - - //----------------- - - //this.parseArgv(); - this.processOptions(program); - - this.debugEnabled = true; - - - }; - - - //--------------------------------------------------------------------- - - DdPubConfig.prototype.setOcsSettings = function(host, venue) { - this.ocsHost = host; - this.ocsAPIDeployment = venue; - }; - - - //--------------------------------------------------------------------- - - DdPubConfig.prototype.getCssoToken = function() { - return this.cssoToken; - }; - - //--------------------------------------------------------------------- - - DdPubConfig.prototype.processOptions = function (program) { - - this.packageName = program.packageName; - this.sourceDir = program.sourceDir; - this.fileWildcard = program.filter; - this.destRoot = program.destPrefix; - - this.retainPath = program.retainPath || false; - this.overwriteEnabled = program.overwrite || false; - this.packageId = null; - this.packageBucket = null; - - //examine glob to make filter decisions - this.filterIncludesPath = (this.fileWildcard.indexOf("/") > -1); - this.fileWildcardRegexObj = globToRegExp(this.fileWildcard); - - this.wasConfiguredSuccessfully = true; - }; - - - - // DdPubConfig.prototype.parseArgv = function () { - // - // let args = argv({ - // packageName: { //name of package to which files will be published - // type: 'string', - // alias: 'p' - // }, - // sourceDir: { //source directory to which we will be listening - // type: 'string', - // alias: 's' - // }, - // destRoot: { //root location in package to which all files will be added (default: "") - // type: 'string', - // alias: 'd' - // }, - // filter: { //client-side filter on which files will be published - // type: 'string', - // alias: 'f' - // }, - // overwrite: { //flag that determines if file can be overwritten (default: false) - // type: 'boolean', - // alias: 'o' - // }, - // retainPath: { //flag that determines if subdir path will be maintained (default: false) - // type: 'boolean', - // alias: 'r' - // } - // }); - // - // //check args - // if (!args.packageName) - // { - // DdLogger.error('Missing required argument: packageName'); - // return null; - // } - // if (!args.sourceDir) - // { - // DdLogger.error('Missing required argument: sourceDir'); - // return null; - // } - // - // //set defaults - // if (!args.filter) - // { - // args.filter = "*"; - // } - // if (!args.destRoot) - // { - // args.destRoot = ""; - // } - // if (!args.retainPath) - // { - // args.retainPath = false; - // } - // if (!args.overwrite) - // { - // args.overwrite = false; - // } - // - // this.packageName = args.packageName; - // this.sourceDir = args.sourceDir; - // this.fileWildcard = args.filter; - // this.destRoot = args.destRoot; - // this.retainPath = args.retainPath; - // this.overwriteEnabled = args.overwrite; - // this.packageId = null; - // - // - // //examine glob to make filter decisions - // this.filterIncludesPath = (this.fileWildcard.indexOf("/") > -1); - // this.fileWildcardRegexObj = globToRegExp(this.fileWildcard); - // - // this.wasConfiguredSuccessfully = true; - // }; - - //--------------------------------------------------------------------- - - DdPubConfig.prototype.isConfigured = function() - { - return this.wasConfiguredSuccessfully; - } - - //--------------------------------------------------------------------- - - DdPubConfig.prototype.isOverwriteEnabled = function() - { - return this.overwriteEnabled; - } - - //--------------------------------------------------------------------- - - - /** - * Returns an OCS path for the local filepath, which is - * relative to the OCS package. - * - * @param {string} filepath Local path of the file to be uploaded - * @return (string} Path part of OCS URL - */ - - DdPubConfig.prototype.getOcsPath = function(filepath) - { - let parent = path.dirname(filepath); - let basename = path.basename(filepath); - - let dbgPrefix = "DdPubConfig:;getOcsPath: "; - DdLogger.debug(dbgPrefix+" Parent = "+parent); - DdLogger.debug(dbgPrefix+" basename = "+basename); - - let srcRoot = this.sourceDir; - - //get the relative pat between srcDir and file's dir - let relativePath = path.relative(srcRoot, parent); - relativePath = upath.normalizeSafe(relativePath); - - DdLogger.debug(dbgPrefix+" relativePath = "+relativePath); - - //we are gonna build the prefix - let prefix = ""; - - //if we have a common destination root, use it - if (! DdUtils.isEmptyOrNullString(this.destRoot)) - { - prefix = upath.normalizeSafe(this.destRoot); - } - - DdLogger.debug(dbgPrefix+" prefix_A = "+prefix); - - //if we want to preserve the relative path, do so - if (this.retainPath) - { - prefix = upath.joinSafe(prefix, relativePath); - } - - DdLogger.debug(dbgPrefix+" prefix_B = "+prefix); - - //does OCS path include the filename? - // let ocsPkgPath = upath.joinSafe(prefix, basename); - let ocsPkgPath = prefix; - - DdLogger.debug(dbgPrefix+" ocsPkgPath_A = "+ocsPkgPath); - - //ensure we start with a slash? - if (!ocsPkgPath.startsWith("/")) { - ocsPkgPath = "/" + ocsPkgPath; - } - - DdLogger.debug(dbgPrefix+" ocsPkgPath-B = "+ocsPkgPath); - - return ocsPkgPath; - }; - - - //--------------------------------------------------------------------- - - - DdPubConfig.prototype.satisfiesFilter = function(fullpath) - { - let _glob = this.fileWildcard; - let _regex = this.fileWildcardRegexObj; - if (!_glob || !_regex) - return true; - - //Assume fullpath is target, but if filter - //is pathless, then just look at the basename? - var target = fullpath; - if (!this.filterIncludesPath) - { - //var basename = DdUtils.extractFilenameFromPath(fullpath); - var basename = path.basename(fullpath); - target = basename; - } - - let regexMatches = _regex.test(target); - return regexMatches; - }; - - - //--------------------------------------------------------------------- - - /** - * Returns a timeout for which we should wait before processing a new - * file event. The reason for this is to add a small delay in the case - * of Windows as apparently Antivirus services can sometimes hold onto - * a file early on, resulting in a read-access issue if we don't wait - * for that to finish. - * @return Timeout in milliseconds - */ - - DdPubConfig.prototype.getFileEventTimeout = function() - { - let sleepMs = 1; - if (DdUtils.isWindows()) { - sleepMs = 5000; - DdLogger.debug("Sleeping for " + sleepMs + " ms (Thanks Windows Antivirus)"); - } - - return sleepMs; - }; - - //--------------------------------------------------------------------- - - //--------------------------------------------------------------------- - - return DdPubConfig; - -})(); - -module.exports = DdPubConfig; diff --git a/src/core/DdQueue.js b/src/core/DdQueue.js deleted file mode 100644 index 1edefad..0000000 --- a/src/core/DdQueue.js +++ /dev/null @@ -1,148 +0,0 @@ -const DdLogger = require('./DdLogger.js').logger; -const { QueueEmptyError, MaxProcessSizeError } = require('./DdError.js'); - -class Processor { - /** - * - * @param {Queue} queue - * @param {number} maxSize - the maximum number of items that can be dequeued at a time; currently we only support 1 - */ - constructor(queue, maxSize=1) { - /** - * counter that works with maxSize to ensure that only "maxSize" number of items can be dequeued - * @type {number} - */ - this.size = 0; - this.queue = queue; - this.maxSize = maxSize; - } - - /** - * Get an items from the queue and then return that item via a promise - */ - process() { - return new Promise((resolve, reject) => { - if (this.queue.isEmpty()) { - reject(new QueueEmptyError("Queue is empty.")); - } - else if (this.size < this.maxSize) { - let node = this.queue.dequeue(); - this.size += 1; - resolve(node); - } - else { - reject(new MaxProcessSizeError("Max process size reached.")); - } - }); - } -} - -class QueueNode { - constructor(key, value) { - /** @type {string | number} */ - this.key = key; - /** @type {object} */ - this.value = value; - this.prev = null; - this.next = null; - } -} - -class Queue { - constructor() { - /** @type {QueueNode} */ - this.head = null; - /** @type {QueueNode} */ - this.tail = null; - /** @type {Object.} */ - this.mapping = {}; - } - - isEmpty() { - return this.head === null && this.tail === null; - } - - /** - * - * @param {string | number} key - * @param {Object} value - */ - enqueue(key, value) { - DdLogger.debug("Called enqueue"); - let node; - if (key in this.mapping) { // case where the key already exist in the queue - node = this.pop(key); - } - else { - node = new QueueNode(key, value); - } - this.mapping[key] = node; - if (this.isEmpty()) { - this.head = node; - this.tail = node; - } - else { - this.tail.next = node; - node.prev = this.tail; - this.tail = node; - } - } - - dequeue() { - DdLogger.debug("Called dequeue"); - let result = null; - if (!this.isEmpty()) { - result = this.head; - let key = result.key; - delete this.mapping[key]; - this.head = this.head.next; - if (this.head) { - this.head.prev = null; - } - else { - this.tail = null; - } - } - return result; - } - - /** - * @param {string | number} key - */ - pop(key) { - DdLogger.debug("Called pop"); - let result = null; - result = this.mapping[key]; - delete this.mapping[key]; - // this is to link up prev node with next node - if (result.prev) { - result.prev.next = result.next; - } - if (result.next) { - result.next.prev = result.prev; - } - if (result === this.head) { - this.head = this.head.next; - } - if (result === this.tail) { - this.tail = this.tail.prev; - } - return result - } - - itemsToList() { - let items = []; - let node = this.head; - while (node) { - items.push(node.value); - node = node.next; - } - return items; - } -} - -module.exports = { - "Queue": Queue, - "QueueNode": QueueNode, - "Processor": Processor -}; \ No newline at end of file diff --git a/src/core/DdSubConfig.js b/src/core/DdSubConfig.js deleted file mode 100644 index c879770..0000000 --- a/src/core/DdSubConfig.js +++ /dev/null @@ -1,222 +0,0 @@ -const fs = require("fs"); -const path = require("path"); -const globToRegExp = require("glob-to-regexp"); -const DdUtils = require("./DdUtils.js"); -const DdLogger = require("./DdLogger.js").logger; -const DdConfig = require("./DdConfig.js"); - -/** - * Definition of the DataDrive Config Class - * - * @type {DdSubConfig} - */ -class DdSubConfig extends DdConfig { - /** - * @constructor - * @param {object} program - Command object from Commander library - * @param {boolean} load_config - Default: true; load configs such as hostnames and csso token; not loading config is used for unit tests - */ - constructor(program, load_config = true) { - super(program, (load_config = load_config)); - this.validateOptions(program); - this.processOptions(program); - } - - //--------------------------------------------------------------------- - - //Replaces parseArgv now that we are using the Commander for options processing - - /** - * Process options from Command object from Commander library - * @param {object} program - object from the commander library - */ - processOptions(program) { - this.packageName = program.packageName; - this.outputDir = program.outputDir; - // file path for location we are tracking the checkpoint file - this.checkpointPath = `${this.outputDir}/.datadrive/checkpoint.txt`; - // file path for location we are tracking the package name file of last time CLI was run - this.savedPackageNamePath = `${this.outputDir}/.datadrive/packagename.txt`; - // file path for location we are tracking the saved search name file of the last time CLI was run - this.savedSavedSearchNamePath = `${this.outputDir}/.datadrive/savedsearchname.txt`; - this.fileWildcard = program.filter; - this.fileWildcardRegexObj = globToRegExp(this.fileWildcard); - this.retainPath = program.retainPath || false; - this.playback = program.playback || false; - this.overwrite = program.overwrite || false; - this.disableDownload = program.disableDownload || false; - this.skipUnchanged = program.skipUnchanged || false; - - // this.pluginsAsync = program.pluginsAsync || false; - // this.pluginsDir = program.pluginsDir; - this.pluginPath = program.pluginPath; - - this.packageId = null; //will get populated later - - //examine glob to make filter decisions - this.filterIncludesPath = program.includeFullPath || false; - this.fileRegex = program.regex; - this.fileRegexObj = this.fileRegex - ? new RegExp(this.fileRegex) - : undefined; - - //saved search - this.savedSearchName = program.savedSearchName; - this.savedSearchType = "personnel"; - - super.configured(); - } - - /** - * Ensure options do not break rules specified in this function - * @param {object} program - */ - validateOptions(program) { - return; // no rules specified yet - } - - /** - * Ensure configs do not break rules specified in this function - * @returns {Promise} Promise object represents a boolean - */ - async validateConfigs() { - if (this.disableDownload && this.pluginPath === undefined) { - DdUtils.errorAndExit( - "Disable download option enabled but missing plugin path option.", - ); - } - - // default will be package name; meaning if you specify a package name, it will go down this code path - if (this.packageName) { - if (this.fileRegex !== undefined && this.fileWildcard !== "*") { - DdUtils.errorAndExit( - "Please specify only 1 filter option; regex or wildcard.", - ); - } - if (this.savedSearchName !== undefined) { - DdUtils.errorAndExit( - "Cannot specify a saved search and package name together.", - ); - } - await this.validateFolderStateFile( - this.savedPackageNamePath, - this.savedSavedSearchNamePath, - this.packageName, - ); - return true; - } - if (this.savedSearchName) { - await this.validateFolderStateFile( - this.savedSavedSearchNamePath, - this.savedPackageNamePath, - this.savedSearchName, - ); - return true; - } - DdUtils.errorAndExit( - "Please specify a package name or a saved search name.", - ); - } - - /** - * Verifies that the specified filename that should exist (packagename.txt or savedsearchname.txt) exists and one that shouldn't does not - * @param {String} filenameShouldExist - * @param {String} filenameShouldNotExist - * @param {String} name - */ - async validateFolderStateFile( - filenameShouldExist, - filenameShouldNotExist, - name, - ) { - // if there is savedsearchname.txt file, we should immediately exist as this folder is for saved search - if (fs.existsSync(filenameShouldNotExist)) { - DdUtils.errorAndExit( - `There is a ${filenameShouldNotExist} file in this folder. Exiting.`, - ); - } - // make sure there is not a packagename.txt file or if there is, the package name matches this.PackageName - if (fs.existsSync(filenameShouldExist)) { - let file = await DdUtils.readFile(filenameShouldExist); - if (name !== file.trim()) { - DdUtils.errorAndExit( - `Package name or saved search name specified (${name}) is not the same as the one specified in ${filenameShouldExist}.`, - ); - } - } - } - - /** - * Returns a full output path for a given filename, - * prepending the config-held output directory. - * - * @param {string} filepath Relative file path (can be empty) - * @param {string} filename File name - * @return (string} Full path or null if missing required - * information - */ - - getOutputLocation(filepath, filename) { - let _outputDir = this.outputDir; - if (DdUtils.isEmptyOrNullString(_outputDir)) return null; - - //assume filepath is empty and filename goes directly - //into outputDir. But if filepath is non-empty, - //apprend it. - let _parentPath = _outputDir; - if (!DdUtils.isEmptyOrNullString(filepath)) - _parentPath = path.join(_outputDir, filepath); - - //now combine out parent path with filename for final result - const _outFilepath = path.join(_parentPath, filename); - - return _outFilepath; - } - - /** - * Returns a full output path for a given file metadata object, - * prepending the config-held output directory. - * - * @param {OCS filemetadata} fileMetadata OCS file metadata object - * @return (string} Full path or null if missing required - * information - */ - - getOutputLocationViaMetadata(fileMetadata) { - if ( - fileMetadata == null || - !( - fileMetadata.hasOwnProperty("ocs_path") && - fileMetadata.hasOwnProperty("ocs_name") - ) - ) - return null; - - let filename = fileMetadata.ocs_name; - let relativePath = this.retainPath ? fileMetadata.ocs_path : null; - let outFilepath = this.getOutputLocation(relativePath, filename); - - return outFilepath; - } - - satisfiesFilter(fullpath) { - //Assume fullpath is target, but if filter - //is pathless, then just look at the basename? - var target = fullpath; - if (!this.filterIncludesPath) { - var basename = DdUtils.extractFilenameFromUrl(fullpath); - target = basename; - } - - if (this.fileRegexObj) { - // always do user given regex first and then wildcard - return DdUtils.filterFilePath(target, this.fileRegexObj); - } else if (this.fileWildcardRegexObj) { - return DdUtils.filterFilePath(target, this.fileWildcardRegexObj); - } else { - return false; - } - } -} - -module.exports = DdSubConfig; diff --git a/src/core/DdUploader.js b/src/core/DdUploader.js deleted file mode 100644 index 089618c..0000000 --- a/src/core/DdUploader.js +++ /dev/null @@ -1,260 +0,0 @@ - - -const axios = require("axios/index"); -const FormData  = require('form-data'); -const fs = require('fs'); -const os = require('os'); -const path = require('path'); -const upath = require('upath'); -//const StreamConcat = require("concat-stream") -const request = require('request'); - -const DdLogger = require('./DdLogger.js').logger; - - -// Pass axios to the imported 'axios-debug' function. -//require('axios-debug')(axios); - -//Inspiration: https://github.jpl.nasa.gov/MIPL/DataDrive-Frontend/blob/develop/src/data/ocsLogic.js#L631 - - - -let DdUploader = (function () { - - const NO_RESPONSE_TIMEOUT = 5 * 60 * 1000; // 5 minute timeout to wait for lambda result - - //--------------------------------------------------------------------- - - /** - * Constructor - * @param ocsServiceUrl Base-URL of the DataDrive middleware - * @param cssotoken CSSO Token - */ - - let DdUploader = function (ocsServiceUrl, cssotoken) { - - this.serviceRoot = ocsServiceUrl; - this.cssoToken = cssotoken; - - this.requestTimeout = null; - - //------------------- - //Config maps - - this.axiosConfig = { - headers: { - Cookie: `ssosession=${this.cssoToken}` - }, -// withCredentials: true, //Do we include this? - }; - - this.streamConfig = {encoding: 'buffer'}; - - //------------------- - //massage data - - if (this.serviceRoot.endsWith("/")) { - let srLen = this.serviceRoot.length; - this.serviceRoot = this.serviceRoot.substring(0, srLen - 1); - } - - }; - - //--------------------------------------------------------------------- - - /** - * Check if the session is still valid by hitting the sso status endpoint. - */ - - DdUploader.prototype.isStillAuthenticated = function() { - return new bbPromise((resolve, reject) => { - axios.get(`${this.serviceRoot}/ssostatus`) - .then(response => { - if (response.status === 200 && - response['data'] !== undefined && - response['data']['authenticated'] !== undefined && - response['data']['authenticated'] === true) { - resolve(true); - return; - } - - reject(Error('No longer Authenticated')); - }) - .catch(err => { - reject(Error(err['message'])); - }); - - }); - }; - - //--------------------------------------------------------------------- - - DdUploader.prototype.isNullOrEmpty = function(input) { - input === null || input === undefined || input === '' - }; - - //--------------------------------------------------------------------- - - DdUploader.prototype.isNullOrEmptyObj = function(input) { - input === null || input === undefined || input === {} - }; - - //--------------------------------------------------------------------- - - DdUploader.prototype.isNullOrEmptyArr = function(input) { - input === null || input === undefined || !Array.isArray(input) || input.length < 1 - }; - - //--------------------------------------------------------------------- - - DdUploader.prototype.resetTimer = function() { - if (this.requestTimeout !== null) { - clearTimeout(this.requestTimeout); - this.requestTimeout = null; - } - } - - //--------------------------------------------------------------------- - - //--------------------------------------------------------------------- - - //--------------------------------------------------------------------- - - - DdUploader.prototype.autoUpload = function(filepath, pkg, bucket, path, isOverwrite, callback) { - - let that = this; - - let restUrl = `${this.serviceRoot}/api/UploadAutoForce`; - - let wrappedCB = function(filepath, err, statusCode, body) { - that.resetTimer(); - callback(filepath, err, statusCode, body); - }; - - this.autoUploadBackground(filepath, pkg, bucket, path, isOverwrite, restUrl, wrappedCB); - - that.resetTimer(); - this.requestTimeout = setTimeout(() => { - let errMsg = "Timeout reached while waiting for upload request to process"; - DdLogger.error(errMsg); - wrappedCB(filepath, errMsg, null, null); - }, NO_RESPONSE_TIMEOUT); - - - }; - - //--------------------------------------------------------------------- - - DdUploader.prototype.autoUploadBackground = function(filepath, ocspkg, s3Bucket, ocspath, - isOverwrite, url, callback) { - - let fileName = path.basename(filepath); - let fileStream = fs.createReadStream(filepath); - - let dbgMesg = "Upload request for: "+filepath+", pkg_id="+ocspkg+", ocs_path="+ocspath+",overwrite="+isOverwrite; - dbgMesg = dbgMesg + "\nUpload URL: "+url; - DdLogger.debug(dbgMesg); - - const _reqOptions = { - url: url, - method: 'POST', - headers: { - Cookie: request.cookie('ssosession=' + this.cssoToken ) - }, - - }; - - var req = request(_reqOptions, function (err, resp, body) { - - if (err) { - dbgMesg = dbgMesg + "\nUpload URL: "+url; - DdLogger.error("Upload error: "+err); - } else { - DdLogger.debug("Request for upload returned"); - } - - DdLogger.debug("Destroying stream associated with "+filepath); - fileStream.destroy(); - //fileStream.close(); - - - callback(filepath, err, resp, body); - - }); - - var form = req.form(); - - let s3Filename = this.createS3Name(s3Bucket, ocspath.toString(), - fileName.toString()); - - DdLogger.debug("s3Filename = "+s3Filename+" from components: bucket: "+s3Bucket+", ocspath: "+ocspath.toString()+", filename: "+fileName.toString()); - - //form.append('file', fileStream); - form.append('pkg_id', ocspkg.toString()); - form.append('ocs_path', ocspath.toString()); - form.append('overwrite', isOverwrite.toString()); - form.append('name', s3Filename); - //form.append('name', fileName.toString()); - form.append('file', fileStream); - - }; - - //--------------------------------------------------------------------- - - DdUploader.prototype.createS3Name = function(s3Bucket, path, filename) { - - if (s3Bucket === undefined || path === undefined) - { - return filename; - } - - // Remove potential trailing slashes from path - if (path !== null) - { - path = path.replace(/\/+$/, ""); - } - - return `s3://${s3Bucket}${path}/${filename}`; - } - - //--------------------------------------------------------------------- - - DdUploader.prototype.extractErrorMessage = function(axiosErr) { - - if (axiosErr['response'] !== undefined) { // it has response object - let responseObj = axiosErr['response']; - if (responseObj['data'] !== undefined) { // it has data object - let responseData = responseObj['data']; - if (typeof responseData === 'object') { // it's JSON object. - if (responseData['message'] !== undefined) { // it has message - return responseData['message']; - } - return JSON.stringify(responseData); - } - if (responseData !== '') { // assuming it's a string, it is not empty - return responseData; - } - - // TODO it may be JSON obj - - } - return `error with status: ${responseObj['status']}`; - } - - if (axiosErr['message'] !== undefined) { // it has error message - return axiosErr['message']; - } - - return 'unkonwn error'; - }; - - - //--------------------------------------------------------------------- - - - return DdUploader; - -})(); - -module.exports = DdUploader; diff --git a/src/core/DdUtils.js b/src/core/DdUtils.js deleted file mode 100644 index 65d04fb..0000000 --- a/src/core/DdUtils.js +++ /dev/null @@ -1,658 +0,0 @@ - - -'use strict'; - -const Validator = require('jsonschema').Validator; -const UrlLib  = require('url'); -const HttpLib = require('http'); -const OsLib = require('os'); -const FsLib = require('fs'); -const PathLib = require('path'); -const request = require('request'); -const util = require('util'); -const fs = require('fs'); -const path = require('path'); -const moment = require('moment'); - -const DdLogger = require('./DdLogger.js').logger; -const DdConstants = require('./DdConstants.js'); -const {AxiosWrapper} = require('./axios_wrapper') - -//Setup the env config using user home dir - -const HOME = OsLib.homedir(); -const SEP = PathLib.sep; -const CFG_FILEDIR = DdConstants.ENV_FILEDIR; -const CFG_FILENAME = DdConstants.ENV_FILENAME; -const CFG_FILE = `${HOME}${SEP}${CFG_FILEDIR}${SEP}${CFG_FILENAME}`; -// const env = require('dotenv').config({ -// path: CFG_FILE -// }); -// if (env.error) { -// throw env.error -// } - -let utils = (function () { - - const OCS_MESG_SCHEMA_NS = "/ocsMessage"; - const OCS_MESG_SCHEMA = { - "type": "object", - "properties": { - "package_id": {"type": "string"}, - "dataset_id": {"type": "string"}, - "ocs_full_name": {"type": "string"}, - "ocs_url": {"type": "string"}, - "package_dataset_event": {"type": "string"}, - "identity": {"type": "string"}, - "package_dataset_event_time": {"type": "number"}, - }, - "required": ["package_id", "dataset_id", "ocs_full_name", "ocs_url", - "package_dataset_event", "identity", - "package_dataset_event_time"] - }; - - const DD_SAVED_SEARCH_MESG_SCHEMA_NS = "/ssMessage"; - const DD_SAVED_SEARCH_MESG_SCHEMA = { - "type": "object", - "properties": { - "package_id": {"type": "string"}, - "dataset_id": {"type": "string"}, - "ocs_full_name": {"type": "string"}, - "ocs_url": {"type": "string"}, - "package_dataset_event": {"type": "string"}, - "identity": {"type": "string"}, - "package_dataset_event_time": {"type": "number"}, - "ss_type": {"type": "string"}, - "ss_name": {"type": "string"}, - "ss_owner": {"type": "string"} - }, - "required": ["package_id", "dataset_id", "ocs_full_name", "ocs_url", - "package_dataset_event", "identity", - "package_dataset_event_time", "ss_type", "ss_name", "ss_owner"] - } - - const OCS_ERR_SCHEMA_NS = "/ocsErrMessage"; - const OCS_ERR_SCHEMA = { - "type": "object", - "properties": { - "error": {"type": "Boolean"}, - "message": {"type": "string"}, - }, - "required": ["error", "message"] - }; - - const DD_UPLOAD_STATUS_NS = "/ddUploadStatusMessage" - const DD_UPLOAD_STATUS_SCHEMA = { - "type": "object", - "properties": { - "upload_status": {"type": "string"}, - "username": {"type": "string"}, - "failed": {"type": "boolean"}, - "upload_name": {"type": "string"}, - }, - "required": ["upload_status", "username", "upload_name", "failed"] - }; - - const validator = new Validator(); - validator.addSchema(OCS_MESG_SCHEMA, OCS_MESG_SCHEMA_NS); - validator.addSchema(DD_SAVED_SEARCH_MESG_SCHEMA, DD_SAVED_SEARCH_MESG_SCHEMA_NS); - validator.addSchema(OCS_ERR_SCHEMA, OCS_ERR_SCHEMA_NS); - validator.addSchema(DD_UPLOAD_STATUS_SCHEMA, DD_UPLOAD_STATUS_NS); - - let utils = function () { - //this.validator = new Validator(); - //this.validator.addSchema(OCS_MESG_SCHEMA, '/ocsMessage'); - //this.validator.addSchema(OCS_ERR_SCHEMA, '/ocsErrMessage'); - - - - }; - - /** - * Validates the JSON object and returns either TRUE if it matches - * the DataDrive Saved Search Message schema. - * @param {Object} mesgObj - The OCS file message object - * @return {boolean} - Either TRUE or FALSE - */ - utils.isValidDDSavedSearchMessage = function (mesgObj) { - let _rslt = utils.validateRequest(mesgObj, DD_SAVED_SEARCH_MESG_SCHEMA, validator); - if (_rslt === true) { - return true; - } - - return false; - } - - /** - * Validates the JSON object and returns either TRUE if it matches - * the DataDrive Upload Status Message schema. - * @private - * - * @param {Object} mesgObj - The OCS file message object - * @return {boolean} - Either TRUE or FALSE - */ - - utils.isValidDDUploadMessage = function (mesgObj) { - - let _rslt = utils.validateRequest(mesgObj, DD_UPLOAD_STATUS_SCHEMA, validator); - if (_rslt === true) { - return true; - } - - return false; - }; - - - /** - * Validates the JSON object and returns either TRUE if it matches - * the OCS Message schema or an error message. - * @private - * - * @param {Object} mesgObj - The OCS file message object - * @return {boolean} - Either TRUE or FALSE - */ - - utils.isErrorOcsMessage = function (mesgObj) { - - let _rslt = utils.validateRequest(mesgObj, OCS_ERR_SCHEMA, validator); - if (_rslt === true) { - return true; - } - - return false; - }; - - - /** - * Validates the JSON object and returns either TRUE if it matches - * the OCS Message schema or an error message. - * @private - * - * @param {Object} mesgObj - The OCS file message object - * @return {boolean|string} - Either TRUE, or an erro message. - */ - - utils.isValidOcsMessage = function (mesgObj) { - - let _rslt = utils.validateRequest(mesgObj, OCS_MESG_SCHEMA, validator); - if (_rslt === true) { - return true; - } - return false; - }; - - /** - * Validates the input parameters and returns either TRUE or an error message. - * @private - * - * @param {JSON} request - The request object (see {}) - * @param {JSON} schema - The schema against which to validate - * @param {function} validator - The validator to use. - * @return {boolean|string} - Either TRUE, or an error message. - */ - utils.validateRequest = function (request, schema, validator) { - let _results = validator.validate(request, schema); - let _ret = true; - if (!_results.valid) { - _ret = 'Invalid input parameters:'; - for (let e of _results.errors) { - _ret = _ret + ' ' + e.toString(); - } - } - return _ret; - }; - - /** - * Check if the current file location can be written to based on DdSubConfig's overwrite property - * - * @param {string} filepath - Path to file location - * @param {Object} config - DdSubConfig that contains information on how to check if we can write to file path - */ - utils.canWriteToLocalFile = function (filepath, config) { - // check if file exists - if (fs.existsSync(filepath)) { - if (config.overwrite) { - // overwrite flag is set to true - return true; - } - return false; // default for file exist is to not overwrite - } - // can write b/c file does not exist - return true; - }; - - /** - * Makes sure that parent directory(s) exists; if not create them recursively - * @param {string} filepath - Path to file location - */ - utils.ensureDirectory = function(filepath) { - let fpParsed = path.parse(filepath); - fs.mkdirSync(fpParsed.dir, {recursive: true}); - } - - /** - * Makes sure that the file path returned is always an absolute path - * @param {string} filepath - file path - * @returns {string} - */ - utils.ensureAbsolutePath = function(filepath) { - if (path.isAbsolute(filepath)) { - return filepath; - } - return path.resolve(filepath); - } - - /** - * Instructions for checking the file system should be here; currently this only checks if the directory exists - * @param {string} path - path to the given directory - */ - utils.fsChecks = function(path) { - // check if directory exists - if (fs.existsSync(path)) { - return true; - } - return false; - } - - utils.extractFilenameFromUrl = function (url) { - let _parsedUrl = UrlLib.parse(url); - let _basename = PathLib.basename(_parsedUrl.pathname); - - return _basename; - }; - - utils.downloadFromUrl = function (url, dest, cb) { - - let _file = fs.createWriteStream(dest); - let request = HttpLib.get(url, function (response) { - response.pipe(_file); - _file.on('finish', function () { - _file.close(cb); // close() is async, call cb after close completes. - }); - }).on('error', function (err) { // Handle errors - fs.unlink(dest); // Delete the file async. (But we don't check the result) - if (cb) - cb(err.message); - }); - } - - //-------------------------------------------- - - utils.isOcsUnauthError = function (err) { - - if (!err) - return false; - - if (!err.message) - return false; - - let _mesg = err.message; - - let flag = _mesg.startsWith("UNAUTHORIZED: "); - return flag; - } - - //-------------------------------------------- - - utils.preauthThen = function(url, token, callMeIfSuccessfull) { - - const reqOptions = { - url: url, - method: 'GET', - headers: { - Cookie: request.cookie('ssosession=' + token) - } - }; - - DdLogger.info("Sending initial HTTP request to "+url+"\n"); - request(reqOptions, (err, res, body) => { - if (err) { - DdLogger.error("Request error: "+err); - return; - } - if (res.headers['set-cookie'] === undefined || res.headers['set-cookie'].length < 1) - { - DdLogger.error('no cookies in http response'); - return; - } - - // TODO check body to see if it's authenticated. - let auth_token = ''; - res.headers['set-cookie'].forEach(e => { - if (e.startsWith('authorization_token')) - { - auth_token = e.split(';', 1)[0].replace('authorization_token=', ''); - DdLogger.debug("Auth_Token = ["+auth_token+"]\n"); - - } - }); //end_forEach - - if (auth_token === '') - { - DdLogger.error('no auth token'); - return; - } - - callMeIfSuccessfull(); - } - ); - - } - - //-------------------------------------------- - - utils.isEmptyOrNullString = function (str) { - - if (!str) - return true; - - if (str === "") - return true; - - return false; - } - - //-------------------------------------------- - - utils.fileExists = function(filepath) { - - try { - if (FsLib.existsSync(filepath)) { - return true; - } - } catch(err) { - } - - return false; - }; - - //-------------------------------------------- - - utils.isWindows = function() { - var opsys = process.platform; - if (opsys == "win32" || opsys == "win64") { - return true; - } - return false; - }; - - /** - * Given wildcard glob regex and user specified regex, check whichever one is valid - * then return whether given filename matches either one. If both glob and regex are - * valid, default to glob - * - * @param {string} filename - file name - * @param {RegExp} regex - regex object based on "--regex" option - */ - utils.filterFilePath = function(filename, regex) { - let regexMatches = regex.test(filename); - return regexMatches; - } - - //--------------------------------------------------------------- - - utils.getCurrentTimeMillis = function() { - let myDate = new Date(); - return myDate.getTime(); - }; - - //--------------------------------------------------------------- - - utils.getCfgFilepath = function(subdir, filename) { - let HOME = OsLib.homedir(); - let SEP = PathLib.sep; - let CFG_FILE = `${HOME}${SEP}${subdir}${SEP}${filename}`; - - return CFG_FILE; - }; - - //--------------------------------------------------------------- - - utils.getDdCfgFilepath = function() { - return utils.getCfgFilepath(DdConstants.CFG_FILEDIR, - DdConstants.CFG_FILENAME); - }; - - utils.getOcsCfgFilepath = function() { - return utils.getCfgFilepath(DdConstants.OCS_CFG_FILEDIR, - DdConstants.OCS_CFG_FILENAME); - - }; - - /** - * Print error message and exit the application - * @param {string|Error} err - */ - utils.errorAndExit = function (err) { - if (err instanceof Error) { - DdLogger.error(err.message); - DdLogger.debug(err.stack); - } - else { - DdLogger.error(err); - } - process.exit(1); - }; - - //--------------------------------------------------------------- - - utils.isValueTrue = function(value) { - if (value) - { - let boolValue = value.toString().toLowerCase() === 'true' ? true : false; - return boolValue; - } - return false; - }; - - //--------------------------------------------------------------- - // TODO: JEFF... need to create regex query for this - // get playback event from DataDrive middleware - utils.getPlaybackEvents = async function(startTime, endTime, config) { - DdLogger.info(`start: ${startTime}, end: ${endTime}`); - let response; - if (config.packageName) { - DdLogger.debug(`getPlaybackEvents with package name: ${config.packageName}`) - response = await utils.getPlaybackPackageEvents(startTime, endTime, config); - } - else { - DdLogger.debug(`getPlaybackEvents with saved search name: ${config.savedSearchName}`) - response = await utils.getPlaybackSavedSearchEvents(startTime, endTime, config); - } - return response - // if (utils.validHTTPResponse(response)) { - // DdLogger.debug(JSON.stringify(response)); // TODO: Remove me - // return response; - // } - // else { - // throw Error(`getPlaybackEvents returned a status code: ${response.statusCode} and body: ${JSON.stringify(response.body)}`); - // } - }; - - utils.getPlaybackPackageEvents = async function(startTime, endTime, config) { - let body = { - start_time: startTime, - end_time: endTime, - all_pkg: false, - pkg: [config.packageId] - }; - if (config.fileRegexObj) { - body['regex'] = config.fileRegex; - } - else { - body['glob_regex'] = config.fileWildcard; - } - const options = { - method: 'POST', - url: `${config.datadriveHost}/api/playback/v2`, - headers: { - 'Content-Type': 'application/json', - Cookie: `ssosession=${config.cssoToken}` - }, - data: body, - } - DdLogger.debug(`getPlaybackPackageEvents request options: ${JSON.stringify(options)}`); - let allResults = [] - let esResult = await AxiosWrapper.builder().request(options) - while (esResult['results'].length > 0) { - allResults.push(esResult['results']) - body['pagination_marker'] = esResult['marker'] - esResult = await AxiosWrapper.builder().request(options) - } - return allResults.flat(2) - // return this.executeDdRequest(url, method, body, config.cssoToken) - }; - - utils.getPlaybackSavedSearchEvents = async function(startTime, endTime, config) { - let body = { - start_time: startTime, - end_time: endTime, - ss_name: config.savedSearchName - }; // currently we will only query for personnel saved searches - const options = { - method: 'POST', - url: `${config.datadriveHost}/api/ss/playback/v2`, - headers: { - 'Content-Type': 'application/json', - Cookie: `ssosession=${config.cssoToken}` - }, - data: body, - } - DdLogger.debug(`getPlaybackSavedSearchEvents request options: ${JSON.stringify(options)}`); - let allResults = [] - let esResult = await AxiosWrapper.builder().request(options) - while (esResult['results'].length > 0) { - allResults.push(esResult['results']) - body['pagination_marker'] = esResult['marker'] - esResult = await AxiosWrapper.builder().request(options) - } - return allResults.flat(2) - }; - - //--------------------------------------------------------------- - // Get saved search; This is used to verify that a saved search exists - /** - * - * @param {String} ss_type "personnel" or "general" - * @param {String} name name of saved search - * @param {String} owner this is for "general" saved search only; name of the owner for a "general" saved search - * @param {DdSubConfig} config config that stores information about DataDrive - */ - utils.getSavedSearch = async function(ss_type, name, owner, config) { - let url; - if (ss_type === "general") { - url = `${config.datadriveHost}/api/saved_search/get/${owner}/${name}`; - } - else { - url = `${config.datadriveHost}/api/saved_search/get/${name}`; - } - return this.executeDdRequest(url, "GET", null, config.cssoToken); - } - - utils.verifySavedSearch = async function(ss_type, name, owner, config, callback) { - let response = await this.getSavedSearch(ss_type, name, owner, config); - if (utils.validHTTPResponse(response)) { - callback() - } - else { - this.errorAndExit('Saved search specified does not exist.'); - } - } - - /** - * Helper function to build and execute a request to DataDrive Middleware Server - * @param {*} url URL of the request - * @param {*} method HTTP Method of the request; this has to be all upper case - * @param {*} body Body of the request - * @param {*} cssoToken CSSO Token that will be passed into `ssosession` header; this will log in the user - * @returns {Promise} Promise with Response object - */ - utils.executeDdRequest = function(url, method, body, cssoToken) { - const reqOptions = { - url: url, - method: method, - headers: { - Cookie: request.cookie('ssosession=' + cssoToken ) - }, - json: true - }; - if (body) { - reqOptions['body'] = body; - } - DdLogger.debug(`Executing DdRequest with reqOptions: ${JSON.stringify(reqOptions)}`); - const requestAsync = util.promisify(request); - let promise = requestAsync(reqOptions); - return promise; - } - - //--------------------------------------------------------------- - // comparator to help sort array of objects with ocs_updated_at field as the field to sort by - utils.playbackEventsComparator = function(event1, event2) { - return new Date(event1.ocs_updated_at).getTime() - new Date(event2.ocs_updated_at).getTime(); - } - - /** - * Check if status code returned from HTTP response is either 2xx (success) or 3xx (redirection) - * https://developer.mozilla.org/en-US/docs/Web/HTTP/Status - * @param {HttpLib.IncomingMessage} response - */ - utils.validHTTPResponse = function(response) { - if (response.statusCode) { - if (response.statusCode >= 200 && response.statusCode < 400) { - return true; - } - } - return false; - } - - /** - * Write Date object to File - * @param {string} filePath - * @param {Date} date - * @returns {Promise} - */ - utils.writeDateToFile = function(filePath, date) { - // write to file in the folder the date - // for multiple download workers, you want to maybe use a queue or something like that - // this is to make sure there are no file read/write collisions - const fsWriteFileAsync = util.promisify(fs.writeFile); - let dateStr = moment(date).format('YYYY-MM-DDTHH:mm:ss.SSSZZ'); // write to local time zone - return fsWriteFileAsync(filePath, dateStr); - } - - /** - * Write Date object to File - * @param {string} filePath - * @param {string} packageName - * @returns {Promise} - */ - utils.writePackageNameToFile = function(filePath, packageName) { - // write package name to file - const fsWriteFileAsync = util.promisify(fs.writeFile); - return fsWriteFileAsync(filePath, packageName); - } - - /** - * Read checkpoint date from given file path - * @param {string} filePath - * @returns {Promise} - */ - utils.getCheckPointDate = function(filePath) { - const fsReadFileAsync = util.promisify(fs.readFile); - return fsReadFileAsync(filePath); - } - - /** - * Read contents from given file path - * @param {string} filePath - * @returns {Promise} - */ - utils.readFile = function(filePath) { - const fsReadFileAsync = util.promisify(fs.readFile); - return fsReadFileAsync(filePath, 'utf8'); - } - - return utils; -})(); - -module.exports = utils; diff --git a/src/core/DdWsClient.js b/src/core/DdWsClient.js deleted file mode 100644 index 80d6742..0000000 --- a/src/core/DdWsClient.js +++ /dev/null @@ -1,229 +0,0 @@ -//TPS imports -const WebSocket = require('ws'); -// const request = require('request'); -// const Validator = require('jsonschema').Validator; -// const UrlLib = require('url'); -// const HttpLib = require('http'); -// const PathLib = require('path'); - -//Local imports -const DdUtils = require('./DdUtils.js'); -const DdLogger = require('./DdLogger.js').logger; -const {jsonTryParse} = require('./utils') -const WebsocketException = require('./exceptions/WebsocketException') - -const MAX_FAILED_ATTEMPTS = 3 //max number of failed to connect attempts before quitting -const REATTEMPT_WAIT_MS = 10000 //time to wait before attempting reconnection -const CHECK_IS_ALIVE_INTERVAL_MS = 2000 - -class DataDriveWsClient { - static builder(config) { - return new DataDriveWsClient(config) - } - constructor(config) { - this._wsHost = null; - this._cssoToken = null; - this._packageId = null; - this._packageName = null; - - this.__eventMsgHandler = _ => {} - this.__errMsgHandler = _ => {} - this.__finalConnectionClosedHandler = _ => {}; - - this._isActive = true; - this._wsClient = null; - this.useReconn = true; - - this._connOpenTime = null; - this._connCloseTime = null; - this._isAlive = true - - this._sequentialClosedEvents = 0; - this.updateConfig(config); - DdLogger.debug(`Connecting to web socket with ${JSON.stringify(config)}.`) - } - - updateConfig(newConfig) { // TODO validation - this._wsHost = newConfig.wsHost; - this._cssoToken = newConfig.cssoToken; - this._packageId = newConfig.packageId; - this._packageName = newConfig.packageName; - this._savedSearchName = newConfig.savedSearchName; - this._savedSearchOwner = newConfig.savedSearchOwner; - } - - setMessageCallback(handler) { - this.__eventMsgHandler = handler - return this - } - setErrorCallback(handler) { - this.__errMsgHandler = handler - return this - } - setFinalConnectionClosedCallback(handler) { - this.__finalConnectionClosedHandler = handler - } - - isActive() { - return this._isActive - } - - close() { - this.useReconn = false; - this._wsClient.close(); - } - - handleWsMessage(wsMessage) { - if (DdUtils.isEmptyOrNullString(wsMessage)) { - DdLogger.error("WS::HandleMessage: empty mesg"); - return - } - let wsJsonMsg = jsonTryParse(wsMessage) - if (wsJsonMsg['error'] !== undefined) { - DdLogger.error(`WS::HandleMessage: non json message: ${wsMessage}`); - return - } - wsJsonMsg = wsJsonMsg['result'] - DdLogger.debug(`WS::HandleMessage: Message receieved: ${JSON.stringify(wsJsonMsg)}`); - // handle datadrive upload status message, which for right now we want to ignore - if (DdUtils.isValidDDUploadMessage(wsJsonMsg)) { - // We want to ignore DataDrive Upload Messages because they aren't useful to the DataDrive CLI - // As such, we will print it to debug in case we ever need to read it. - DdLogger.debug(`WS::HandleMessage: Receieved DataDrive Upload Message: ${JSON.stringify(wsJsonMsg)}`); - return; - } - //handle formatted error message from WS host - if (DdUtils.isErrorOcsMessage(wsJsonMsg)) { - DdLogger.error(`WS::HandleMessage: Received error message from WS host: ${JSON.stringify(wsJsonMsg)}`); - this.__errMsgHandler(wsJsonMsg) - return; - } - - //check if we actually received a valid file message that is either OCS message or one that builds on top of an OCS message (ie. Saved Search Message) - let ocsValidResult = DdUtils.isValidOcsMessage(wsJsonMsg); - if (ocsValidResult !== true) { - DdLogger.error("WS::HandleMessage: Could not validate WS-based OCS message: " + wsMessage); - DdLogger.error("WS::HandleMessage: More info: " + ocsValidResult); - return; - } - this.__eventMsgHandler(wsJsonMsg) - } - - __onOpen() { - this._connOpenTime = DdUtils.getCurrentTimeMillis(); - this._connCloseTime = null; - this._isActive = true; - this._isAlive = true - this._sequentialClosedEvents = 0; //since we have an open event, zero out close event count - DdLogger.info('Connected to DataDrive WS service '); - // Silence upload status events as we don't care about them and will want to ignore them. - this._wsClient.send(JSON.stringify({send_upload_status_msg: false})) - - //send websocket the packageId in which we are interested - if (this._packageId) { - DdLogger.debug("Requesting OCS events from package '" + this._packageName + "' (" + this._packageId + ")..."); - this._wsClient.send(JSON.stringify({ - client_type: 'dd_cli', - all_pkg: false, - pkg: [this._packageId], - })); - } else if (this._savedSearchName) { - DdLogger.debug("Requesting Saved Search events '" + this._savedSearchName + "' ..."); - this._wsClient.send(JSON.stringify({ - client_type: "NA", - all_pkg: false, - pkg: ["invalidId"]})) // this disables package level events - let payload = { - 'interested_saved_searches': [ - { - type: 'personal', - owner: this._savedSearchOwner, - name: this._savedSearchName - } - ] - }; - this._wsClient.send(JSON.stringify(payload)); - } else { - DdUtils.errorAndExit("Error during web socket open. Package Name was not provided or incorrect, or saved search name was not provided.") - } - } - - __onClose(event) { - this._connCloseTime = DdUtils.getCurrentTimeMillis(); - let connTimeInfo = ""; - if (!(this._connCloseTime === null || this._connOpenTime === null)) { - let connTime = this._connCloseTime - this._connOpenTime; - connTimeInfo = "(alive for " + (connTime / 1000) + " seconds)"; - } - - DdLogger.info("Disconnected from websocket " + connTimeInfo + ""); - DdLogger.info("WS.close(): " + JSON.stringify(event)); - - this._isActive = false; - this._sequentialClosedEvents = this._sequentialClosedEvents + 1; - - if (this.useReconn) { - if (this._sequentialClosedEvents >= MAX_FAILED_ATTEMPTS) { - DdLogger.error("WS.close(): Maximum connection attempts have failed. Giving up."); - //console.log("WS.close(): Maximum connection attempts have failed. Giving up."); - this.__finalConnectionClosedHandler(); - return; - } - let reconnTime = REATTEMPT_WAIT_MS * this._sequentialClosedEvents; - DdLogger.info("WS.close(): We are going to try reconnecting shortly..."); - const instance = this - //console.log("WS.close(): We are going to try reconnecting shortly..."); - setTimeout(() => instance.buildWebSocketClient(), reconnTime); - } - } - - __onError(errMessage) { - let now = DdUtils.getCurrentTimeMillis(); - DdLogger.error("Error happened with websocket [" + now + "] : " + JSON.stringify(errMessage)); - this.__errMsgHandler(errMessage) - } - - __onMessage(message) { - try { - this.handleWsMessage(message) - } catch (error) { - DdLogger.printError(error); - DdLogger.error("Error occurred while handling WS message: " + JSON.stringify(message)); - } - } - - __checkSocketStatus() { - if (this._isAlive === false) { - DdLogger.error('closing socket coz isAlive is false. This is a temporary workaround') - throw new WebsocketException('closing socket coz isAlive is false') - } - this._isAlive = false - this._wsClient.ping(() => {}) - } - - startSession() { - this.buildWebSocketClient() - return this - } - - buildWebSocketClient() { - const instance = this - const wsOptions = { - // rejectUnauthorized: false, // enable this when testing it locally where https is using self-signed certs - headers: { - Cookie: `ssosession=${this._cssoToken}` - } - }; - - DdLogger.debug("Connecting to " + this._wsHost + "...\n"); - //console.log("Connecting to "+this._wsHost+"...\n"); - this._wsClient = new WebSocket(this._wsHost, [], wsOptions); - this._wsClient.on('pong', () => instance._isAlive = true) // result of ping. if it responds, it's still alive - this._wsClient.on('open', () => instance.__onOpen()) - this._wsClient.on('close', event => instance.__onClose(event)) - this._wsClient.on('error', errEvent => instance.__onError(errEvent)) - this._wsClient.on('message', message => instance.__onMessage(message)) - setInterval(() => instance.__checkSocketStatus(), CHECK_IS_ALIVE_INTERVAL_MS) - } -} -exports.DataDriveWsClient = DataDriveWsClient diff --git a/src/core/EmptyPromise.js b/src/core/EmptyPromise.js deleted file mode 100644 index ebbca10..0000000 --- a/src/core/EmptyPromise.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @author wphyo - * Created on 11/24/20. - */ -const bbPromise = require('bluebird'); -class EmptyPromise { - constructor() { - this._callbacks = null; - this._done = false; - let instance = this; - this._p = new bbPromise((resolve, reject) => {instance._callbacks = { resolve, reject }}); - } - - done() { - return this._done; - } - - resolve(obj) { - this._callbacks.resolve(obj); - this._done = true; - return this._p; - } - - reject(obj) { - this._callbacks.reject(obj); - this._done = true; - return this._p; - } - - get() { - return this._p; - } - - static builder() { - return new EmptyPromise(); - } -} -exports.EmptyPromise = EmptyPromise; -/** - * @author wphyo - * Created on 6/1/22. - */ diff --git a/src/core/OcsUtils.js b/src/core/OcsUtils.js deleted file mode 100644 index b4cafdd..0000000 --- a/src/core/OcsUtils.js +++ /dev/null @@ -1,180 +0,0 @@ -const util = require('util'); -const DdConsts = require('./DdConstants.js'); -const SsoToken = require('./SsoToken.js'); -const DdUtils = require('./DdUtils.js'); -const DdLogger = require('./DdLogger.js').logger; -const {EmptyPromise} = require('./EmptyPromise') - -class OcsUtils { - static builder(ocsClient, ocsToken) { - return new OcsUtils(ocsClient, ocsToken) - } - constructor(ocsClient, ocsToken) { - this._ocsClient = ocsClient; - this._token = ocsToken; - } - - __validateOCSResult (err, result, methodName) { - if (err !== null) { - return `${methodName}-ends-in-error: ${err.toString()}`; - } - if (result === null || result === undefined) { - return `result for ${methodName} is NULL or UNDEFINED`; - } - if (result['statusCode'] !== 200) { // status return is not 200 - if (result['error'] !== undefined && result['error'] !== null) { // there is an error message - let errMsg = JSON.stringify(result['error']); - DdLogger.error(`ocs-api-error for ${methodName}: ${errMsg}`, this._user); - return errMsg; - } else { - return `ocs status for ${methodName} returned is not 200. code: ${result['statusCode']}`; - } - } - return undefined; - } - - async __executeOCS (param, methodName) { - DdLogger.debug(`${methodName} : ${util.inspect(param, {depth: null})}`); - const instance = this; - - let promise = EmptyPromise.builder() - this._ocsClient[methodName](param, (err, result) => { - let validateOCSResponse = instance.__validateOCSResult(err, result, methodName); // checking the result - if (validateOCSResponse !== undefined) { - DdLogger.error("Error occurred while requesting all package information from OCS."); - DdLogger.printError(validateOCSResponse); - - if (DdUtils.isOcsUnauthError(validateOCSResponse)) { // TODO - DdLogger.error("Please ensure your OCS CSSO login credentials are valid."); - } - promise.reject(new Error(validateOCSResponse)); - return; - } - promise.resolve(result['data']); - }); - return await promise.get(); - } - - toBucketKey(s3Url) { - if (!s3Url.startsWith(DdConsts.S3_PROTOCOL)) { - return undefined - } - const _matches = s3Url.match(DdConsts.S3_URL_REGEX); - return { - bucket: _matches[1], - key: _matches[2] - } - } - - /** - * Returns a permalink to an object indexed in OCS. Copied via https://github.jpl.nasa.gov/M2020-CS3/m2020-data-lake repo - * - * @param {string} pepUrl - The URL of the PEP server - * @param {string} url - The URL of the data object that was indexed in OCS. Typeically, this is an S3 URL. - * @return {string} - A permalink to the URL. - */ - getPermalinkviaPEP(pepUrl, url) { - const _bucketKey = this.toBucketKey(url) - if (_bucketKey && _bucketKey.bucket && _bucketKey.key) { - // This is an S3 URL. - if (pepUrl) { - return `${pepUrl}/${_bucketKey.bucket}/${_bucketKey.key}` - } else { - throw Error('The PEP server information is not defined. The configuration needs to be updated.') - } - } else { - // Not an S3 URL, so we just return as is. Assume the resource is already protected by CSSO. - return url - } - } - - createLsQuery(packageId, ocsFullname, expr) { - let patternsArray = [ `${ocsFullname}` ]; - let searchDoc = { - packageName: packageId, - patterns: patternsArray, - dirOnly: false, - recursive: false, - }; - - if (expr) - { - searchDoc.expr = expr; - } - - return searchDoc; - } - - createLsRequest(packageId, ocsFullname, expr) { - - let lsQueryObj = this.createLsQuery(packageId, ocsFullname, expr); - return { - csso: { - sessionToken: this._token - }, - input: lsQueryObj - } - } - - /** - * - * @param packageName : String - * @return {Promise<{packageS3Bucket: (null|*), packageId: *}|{packageS3Bucket: null, packageId: null}>} - */ - async translatePackageNameToId(packageName) { - if (!this._ocsClient) { - throw new Error("No OCS client available"); - } - if (!this._token) { - throw new Error("No OCS token set"); - } - if (DdUtils.isEmptyOrNullString(packageName)) { - throw new Error("No packageName parameter"); - } - let _descAllPkgsReq = { - csso: { - sessionToken: this._token - } - } - const ocsPkgs = await this.__executeOCS(_descAllPkgsReq, 'describeAllPackages') - if(ocsPkgs.length < 1) { - DdLogger.warn('no package found in OCS') - return { - packageId: null, - packageS3Bucket: null, - } - } - const filteredPkg = ocsPkgs.filter(e => e['name'] === packageName) - if (filteredPkg.length < 1) { - DdLogger.debug(`no package name: ${packageName} in OCS`) - return { - packageId: null, - packageS3Bucket: null, - } - } - return { - packageId: filteredPkg[0]['package_id'], - packageS3Bucket: filteredPkg[0]['s3Bucket'] === undefined ? null : filteredPkg[0]['s3Bucket'] - } - } - - async getOcsFileMetadata(packageName, ocsFullname) { - if (!ocsFullname || ocsFullname === "") { - DdLogger.error("getOcsFileMetadata: Missing ocsFullname parameter"); - return - } - const ocsFileArray = await this.__executeOCS(this.createLsRequest(packageName, ocsFullname, null), 'searchLS') - - if (ocsFileArray.length < 1) { - DdLogger.debug(`no file found for ${ocsFullname}`) - return {} - } - if (ocsFileArray.length > 1) { - DdLogger.warn(`OCS sent multiple results (count = ${ocsFileArray.length}) for the OCS LS query for: ${ocsFullname}`); - DdLogger.warn("If this issue exists beyond G6.0 testing, please inform OCS/CS3 team (its their bug?)"); - } - return ocsFileArray[0] - } -} - -module.exports = OcsUtils diff --git a/src/core/SsoToken.js b/src/core/SsoToken.js deleted file mode 100644 index ac5711b..0000000 --- a/src/core/SsoToken.js +++ /dev/null @@ -1,107 +0,0 @@ -/** - * @author wphyo - * Created on 6/1/22. - */ -// Interface to the OCS SSO token and also a facility to keep it -// active through periodic URL cookie-based requests to an OCS service URL. -// - -'use strict'; - -const fs = require('fs'); -const os = require('os'); -const path = require('path'); -const request = require('request'); - -const DdUtils = require('./DdUtils'); -const DdLogger = require('./DdLogger.js').logger; - -class SsoToken { - constructor() { - this.__ssoTokenValue = null // This should be a string value - this.__ssoTokenExpiration = null // This should be a string value - - this.__intervalMinutes = 1; - this.__intervalSecPerMin = 60; - this.__intervalMsecPerSec = 1000; - this.__intervalMillis = this.__intervalMinutes * this.__intervalSecPerMin * this.__intervalMsecPerSec; - - this.__timerObj = null; - this.__checkAuthToken = true; - - //timestamps on auth requests and success - this.__performAuthMetrics = true; - this.__lastAuthAttempt = null; - this.__lastAuthSuccess = null; - this.__lastAuthAttemptMax = 3; - this.__lastAuthTimeout = this.__lastAuthAttemptMax * this.__intervalMillis; - } - - loadToken(sessionPath=null, expirationPath=null) { - try { - //CSSO token - const homedir = os.homedir(); - let sesPath = sessionPath !== null ? sessionPath : path.join(homedir, ".cssotoken", "ssosession") - let expPath = expirationPath !== null ? expirationPath : path.join(homedir, ".cssotoken", "expiration") - - //console.log("sesPath "+sesPath); - this.__ssoTokenValue = fs.readFileSync(sesPath, 'utf8'); - this.__ssoTokenExpiration = fs.readFileSync(expPath, 'utf8'); - - if ( DdUtils.isEmptyOrNullString(this.__ssoTokenValue)) { - DdUtils.errorAndExit('SsoToken:: Empty cssotoken. Consider re-initing your credentials'); - } - } catch (error) { - DdLogger.error(error.message); - DdLogger.debug(error.stack); - DdUtils.errorAndExit('SsoToken:: Error occurred during retrieval of cssotoken.') - } - } - - isTokenAboutToExpired(hours=1) { - this.getTokenExpiration() - if (!this.__ssoTokenExpiration) { - DdUtils.errorAndExit('SsoToken:: Empty cssotoken. Consider re-initing your credentials'); - return false - } - // Check that it has not expired. - // Note that the expiration time written by CSSO is in seconds, not milliseconds. - const _expireTime = Number.parseInt(this.__ssoTokenExpiration) - let expireDate = new Date(_expireTime * 1000) // Date object should be in milliseconds, so multiply it by 1000 - expireDate.setHours(expireDate.getHours() - hours) - let date = new Date(Date.now()) - return date >= expireDate - } - - getToken() { - if (DdUtils.isEmptyOrNullString(this.__ssoTokenValue)) { - this.loadToken() - } - return this.__ssoTokenValue; - } - - setToken() { - // validate input; make sure it is a string - if (typeof value != "string") { - throw Error('Token should be a string') - } - this.__ssoTokenValue = value - } - - getTokenExpiration() { - if (DdUtils.isEmptyOrNullString(this.__ssoTokenExpiration)) { - this.loadToken() - } - return this.__ssoTokenExpiration - } - - setTokenExpiration(tokenExpirationValue) { - // validate input to be of length 10 and is a string - if (typeof tokenExpirationValue != "string" || tokenExpirationValue.length !== 10) { - throw Error('Token should be a string and of length 10') - } - this.__ssoTokenExpiration = tokenExpirationValue - } -} - -module.exports = SsoToken; diff --git a/src/core/axios_wrapper.js b/src/core/axios_wrapper.js deleted file mode 100644 index 988cdc5..0000000 --- a/src/core/axios_wrapper.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @author wphyo - * Created on 10/1/20. - */ -const axios = require('axios') - -class AxiosWrapper { - async request(options) { - try { - let result = await axios.request(options) - return result.data - } catch (e) { - let err = new Error() - err.message = JSON.stringify(e.response.data) - err.statusCode = e.response.status - throw err - } - } - static builder() { - return new AxiosWrapper() - } -} -exports.AxiosWrapper = AxiosWrapper diff --git a/src/core/config.js b/src/core/config.js index 42025fe..b6c32c5 100644 --- a/src/core/config.js +++ b/src/core/config.js @@ -25,7 +25,7 @@ function getConfig() { try { config = JSON.parse(cfgFile); config.logdir = config.logdir || DdConstants.DEFAULT_LOG_PATH; - config.venue = config.venue || DdConstants.DEFAULT_VENUE; + config.authType = config.authType || DdConstants.DEFAULT_AUTH_TYPE; return config; } catch (e) { if (ignoreErrors) return {}; diff --git a/src/core/exceptions/WebsocketException.js b/src/core/exceptions/WebsocketException.js deleted file mode 100644 index 6e13668..0000000 --- a/src/core/exceptions/WebsocketException.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @author wphyo - * Created on 7/19/21. - */ -class WebsocketException extends Error { - constructor(message) { - super(message) - this.name = 'WebsocketException' - } -} -module.exports = WebsocketException diff --git a/src/core/ocs_utils.js b/src/core/ocs_utils.js index 47e653e..0689d3f 100644 --- a/src/core/ocs_utils.js +++ b/src/core/ocs_utils.js @@ -3,18 +3,19 @@ const fs = require("fs"); const https = require("https"); const fetch = require("node-fetch"); const urllib = require("url"); +const nodeUtil = require("node:util"); +const exec = nodeUtil.promisify(require("node:child_process").exec); const ocsJSClientMdms = require("@gov.nasa.jpl.ammos.ids/mdms-aocs-js-client"); -const ocsJSClientM20 = require("@gov.nasa.jpl.m2020.cs3/ocs-js-client"); +const ocsJSClientM20 = + require("@gov.nasa.jpl.m2020.cs3/ocs-js-client").OcsClient; const CSsoClient = require("@gov.nasa.jpl.m2020.cs3/ocs-js-client/core/csso"); const SsoClient = require("@gov.nasa.jpl.ammos.ids/mdms-aocs-js-client/core/sso"); const DdLogger = require("./DdLogger").logger; const DdConsts = require("./DdConstants"); -const DdUtils = require("./DdUtils"); const config = require("./config.js").config; -const SsoToken = require("./SsoToken.js"); const utils = require("./utils.js"); const OCS_MESG_SCHEMA = { @@ -107,7 +108,7 @@ function getPackageID(ocsClient, package) { return new Promise((resolve, reject) => { ocsClient.client.describeAllPackages(options, (err, res) => { if (err) { - DdUtils.errorAndExit(`Error making request to OCS: ${err}`); + DdLogger.errorAndExit(`Error making request to OCS: ${err}`); } resolve(res.data.find((pkg) => pkg.name === package)); }); @@ -149,9 +150,10 @@ async function downloadFileFromMetadata( ocsClient, fileData, destPath, - overwrite = false, + options, ) { // CHECK FOR OVERWRITE + const overwrite = Boolean(options.overwrite); let fileExists; try { fileExists = !(await fs.promises.access(destPath)); @@ -163,7 +165,7 @@ async function downloadFileFromMetadata( return; } - DdLogger.debug(`Write out file ${fileData.ocs_full_name} to ${destPath}`); + DdLogger.info(`Write out file ${fileData.ocs_full_name} to ${destPath}`); // Check that the output dir exists, create if not const destDir = path.dirname(destPath); @@ -190,9 +192,9 @@ async function downloadFileFromMetadata( fileData, ); - const options = { + const fetchOptions = { headers: { - Cookie: `${DdConsts.SSO_SESSION_KEY_LOOKUP[config.venue]}=${ + Cookie: `${DdConsts.SSO_SESSION_KEY_LOOKUP[config.authType]}=${ ocsClient.token }`, }, @@ -202,11 +204,11 @@ async function downloadFileFromMetadata( time: true, }; - if (config.venue === "MGSS") { - options.headers["Content-Type"] = "application/json"; + if (config.authType === "MGSS") { + fetchOptions.headers["Content-Type"] = "application/json"; } - let res = await fetch(downloadUrl, options); + let res = await fetch(downloadUrl, fetchOptions); if (!res.ok) { DdLogger.error( @@ -215,10 +217,10 @@ async function downloadFileFromMetadata( return; } - if (config.venue === "MGSS") { + if (config.authType === "MGSS") { const presigned_url_msg = await res.json(); - delete options.headers["Content-Type"]; - res = await fetch(presigned_url_msg.presigned_url, options); + delete fetchOptions.headers["Content-Type"]; + res = await fetch(presigned_url_msg.presigned_url, fetchOptions); if (!res.ok) { DdLogger.error( `Couldn't download file: ${fileData.ocs_full_name}: ${res}`, @@ -234,6 +236,23 @@ async function downloadFileFromMetadata( fileStream.on("finish", resolve); }); + // Kick off callback command if there is one + if (options.callback) { + const env = { + ...process.env, + FILENAME: getFilenameFromOCSURL(fileData.ocs_full_name), + SRC_PATH: fileData.ocs_full_name, + DEST_PATH: destPath, + }; + const { stdout, stderr } = await exec(options.callback, { env }); + DdLogger.info(stdout); + if (stderr) { + DdLogger.error( + `Error encountered running file download callback: "${options.callback}": ${stderr}`, + ); + } + } + // Check that file on disk matches checksum // const hash = await utils.getFileHash(destPath); // if (hash !== fileData.ocs_etag) { @@ -241,16 +260,11 @@ async function downloadFileFromMetadata( // } } -function getCSSOToken() { - const CSSOAuth = new SsoToken(); - return CSSOAuth.getToken(); -} - async function getMiddlewareSettings(config, token) { const options = { method: "GET", headers: { - Cookie: `${DdConsts.SSO_SESSION_KEY_LOOKUP[config.venue]}=${token}`, + Cookie: `${DdConsts.SSO_SESSION_KEY_LOOKUP[config.authType]}=${token}`, }, httpsAgent: new https.Agent({ rejectUnauthorized: false }), }; @@ -269,11 +283,13 @@ async function getMiddlewareSettings(config, token) { let outMsg = `Can't connect to middleware endpoint at url: ${url}.`; if (res && res.status === 401) { const authProgram = - config.venue === "M20" ? "CREDSS" : "/etc/request_ssotoken.sh"; + config.authType === "M20" + ? "CREDSS" + : "/etc/request_ssotoken.sh"; outMsg = `Authentication error connecting to DataDrive. Have you updated your credentials via ${authProgram} recently?`; } - return DdUtils.errorAndExit(outMsg); + return DdLogger.errorAndExit(outMsg); } DdLogger.debug( @@ -297,11 +313,11 @@ async function getOCSClient(options) { let token; try { token = - config.venue === "MGSS" + config.authType === "MGSS" ? SsoClient.cliGetSSOTokens(venue) : CSsoClient.cliGetCSSOTokens(venue); } catch (e) { - DdUtils.errorAndExit(e.message); + DdLogger.errorAndExit(e.message); } const middlewareSettings = await getMiddlewareSettings(config, token); @@ -311,7 +327,7 @@ async function getOCSClient(options) { }; let client; - switch (config.venue) { + switch (config.authType) { case "MGSS": ocsConfig.ocsEndpointPort = middlewareSettings.ocs_endpoint_port; client = new ocsJSClientMdms(ocsConfig); @@ -324,7 +340,7 @@ async function getOCSClient(options) { return { client, token, - ssoKey: DdConsts.SSO_KEY_LOOKUP[config.venue], + ssoKey: DdConsts.SSO_KEY_LOOKUP[config.authType], username: token.split(":") ? token.split(":")[1] : "", }; } @@ -359,6 +375,7 @@ async function getPlaybackEvents( } if (options.filter) { + console.log(options.filter); body.glob_regex = options.filter.endsWith("*") ? options.filter : options.filter + "*"; diff --git a/src/core/utils.js b/src/core/utils.js index 768187e..f8be8d9 100644 --- a/src/core/utils.js +++ b/src/core/utils.js @@ -7,12 +7,16 @@ const Validator = require("jsonschema").Validator; const v = new Validator(); const fs = require("fs"); const crypto = require("crypto"); +const OsLib = require("os"); +const FsLib = require("fs"); +const PathLib = require("path"); +const DdConstants = require("./DdConstants.js"); const isValidJson = (obj, schema) => { - if (obj === null || obj === undefined) { - return false; - } - return v.validate(obj, schema).valid; + if (obj === null || obj === undefined) { + return false; + } + return v.validate(obj, schema).valid; }; /** @@ -21,56 +25,65 @@ const isValidJson = (obj, schema) => { * @return {{result: undefined, error: string}|{result: any, error: undefined}} */ const jsonTryParse = (input) => { - try { - return { - result: JSON.parse(input), - error: undefined, - }; - } catch (error) { - return { - result: undefined, - error: error.toString(), - }; - } + try { + return { + result: JSON.parse(input), + error: undefined, + }; + } catch (error) { + return { + result: undefined, + error: error.toString(), + }; + } }; async function getFileHash(filePath) { - const hashPromise = new Promise((resolve, reject) => { - const hash = crypto.createHash("md5"); - const readableStream = fs.createReadStream(filePath); - readableStream.on("data", (chunk) => { - hash.update(chunk); - }); - readableStream.on("end", (_) => { - resolve(hash.digest("hex")); - }); - }); - return await hashPromise; + const hashPromise = new Promise((resolve, reject) => { + const hash = crypto.createHash("md5"); + const readableStream = fs.createReadStream(filePath); + readableStream.on("data", (chunk) => { + hash.update(chunk); + }); + readableStream.on("end", (_) => { + resolve(hash.digest("hex")); + }); + }); + return await hashPromise; } function filterToRegexp(filter) { - let filterString = filter.replace(/[.+?^${}()|[\]\\]/g, "\\$&"); - filterString = "^" + filterString.replace(/\*/g, ".*") + "$"; - return new RegExp(filterString); + let filterString = filter.replace(/[.+?^${}()|[\]\\]/g, "\\$&"); + filterString = "^" + filterString.replace(/\*/g, ".*") + "$"; + return new RegExp(filterString); } function parseLogRollingOptionIntoWinstonDatePattern(optionString) { - switch (optionString) { - case "monthly": - return "YYYYMM"; - case "weekly": - return "YYYY-[w]w"; - case "daily": - return "YYYYMMDD"; - default: - return optionString; - } + switch (optionString) { + case "monthly": + return "YYYYMM"; + case "weekly": + return "YYYY-[w]w"; + case "daily": + return "YYYYMMDD"; + default: + return optionString; + } +} + +function getCfgFilepath() { + let HOME = OsLib.homedir(); + let SEP = PathLib.sep; + let CFG_FILE = `${HOME}${SEP}${DdConstants.CFG_FILEDIR}${SEP}${DdConstants.CFG_FILENAME}`; + + return CFG_FILE; } module.exports = { - isValidJson, - jsonTryParse, - getFileHash, - filterToRegexp, - parseLogRollingOptionIntoWinstonDatePattern, + isValidJson, + jsonTryParse, + getFileHash, + filterToRegexp, + parseLogRollingOptionIntoWinstonDatePattern, + getCfgFilepath, }; diff --git a/src/core/websocket_utils.js b/src/core/websocket_utils.js index b74a34b..5012d47 100644 --- a/src/core/websocket_utils.js +++ b/src/core/websocket_utils.js @@ -25,7 +25,7 @@ function getWSClient(ocsClient, options) { const wsOptions = { headers: { - Cookie: `${DdConsts.SSO_SESSION_KEY_LOOKUP[config.venue]}=${ + Cookie: `${DdConsts.SSO_SESSION_KEY_LOOKUP[config.authType]}=${ ocsClient.token }`, }, diff --git a/src/ddrv-config.js b/src/ddrv-config.js index 0c00de4..919d9e5 100644 --- a/src/ddrv-config.js +++ b/src/ddrv-config.js @@ -3,10 +3,10 @@ const { Command, Option } = require("commander"); const program = new Command(); const Table = require("easy-table"); -const DdUtils = require("./core/DdUtils.js"); const DdConsts = require("./core/DdConstants.js"); const DdLogger = require("./core/DdLogger.js").logger; const getConfig = require("./core/config.js").getConfig; +const utils = require("./core/utils.js"); function displayExistingConfig() { const t = new Table(); @@ -14,7 +14,7 @@ function displayExistingConfig() { try { config = getConfig(); } catch (e) { - DdUtils.errorAndExit(e.message); + DdLogger.errorAndExit(e.message); } [ @@ -52,14 +52,17 @@ function writeNewConfig(options) { DdConsts.DEFAULT_LOG_PATH, logDatePattern: options.logDatePattern, gzipRollingLogs: !options.noGzip, - authType: options.authType, + authType: + options.authType || + existingConfig.authType || + DdConsts.DEFAULT_AUTH_TYPE, }; - const cfgPath = DdUtils.getDdCfgFilepath(); + const cfgPath = utils.getCfgFilepath(); try { fs.writeFileSync(cfgPath, JSON.stringify(outObj)); } catch (e) { - DdUtils.errorAndExit( + DdLogger.errorAndExit( `Unable to write configuration file at ${cfgPath}. Do you have write permission to this location?`, ); } @@ -88,9 +91,10 @@ function main() { ); program.addOption( - new Option("-a, --auth-type ", "Auth Type") - .choices(["M20", "MGSS"]) - .default("M20"), + new Option("-a, --auth-type ", "Auth Type").choices([ + "M20", + "MGSS", + ]), ); program.parse(); @@ -98,7 +102,7 @@ function main() { const options = program.opts(); // Handle no arguments (just display existing config) - if (!Object.keys(options).filter((key) => key !== "authType").length) { + if (!Object.keys(options).length) { return displayExistingConfig(); } diff --git a/src/ddrv-license.js b/src/ddrv-license.js new file mode 100644 index 0000000..69249f6 --- /dev/null +++ b/src/ddrv-license.js @@ -0,0 +1,10 @@ +const { Command, Option } = require("commander"); +const program = new Command(); + +const licenseText = `${LICENSE_TEXT}`; + +function main() { + console.log(licenseText); +} + +main(); diff --git a/src/ddrv-publish.js b/src/ddrv-publish.js index 515b661..a56f159 100644 --- a/src/ddrv-publish.js +++ b/src/ddrv-publish.js @@ -5,7 +5,6 @@ const program = new Command(); const chokidar = require("chokidar"); const DdConsts = require("./core/DdConstants.js"); -const DdUtils = require("./core/DdUtils.js"); const DdLogger = require("./core/DdLogger.js").logger; const ocs_utils = require("./core/ocs_utils.js"); const utils = require("./core/utils.js"); @@ -17,14 +16,14 @@ function validateOptions(options = {}) { // Does the input dir exist? if (!fs.existsSync(options.sourceDir)) { - DdUtils.errorAndExit( + DdLogger.errorAndExit( `Can't find source directory ${options.sourceDir}, quitting...`, ); } if (errors.length) { const outMsg = errors.join("\n"); - return DdUtils.errorAndExit(outMsg); + return DdLogger.errorAndExit(outMsg); } return options; @@ -140,11 +139,11 @@ async function main() { options.packageName, ); if (!packageInfo) { - DdUtils.errorAndExit(`Cannot find package: ${options.packageName}`); + DdLogger.errorAndExit(`Cannot find package: ${options.packageName}`); } if (!packageInfo.s3Bucket) { - DdUtils.errorAndExit( + DdLogger.errorAndExit( `Package ${options.packageName} does not have an s3Bucket configured and thus can't be published to using this tool.`, ); } diff --git a/src/ddrv-show.js b/src/ddrv-show.js index 369eaff..ebc5c97 100644 --- a/src/ddrv-show.js +++ b/src/ddrv-show.js @@ -3,7 +3,6 @@ const program = new Command(); const Table = require("easy-table"); const DdConsts = require("./core/DdConstants.js"); -const DdUtils = require("./core/DdUtils.js"); const DdLogger = require("./core/DdLogger.js").logger; const ocs_utils = require("./core/ocs_utils.js"); @@ -11,7 +10,7 @@ async function getPackages() { const ocsClient = await ocs_utils.getOCSClient(); ocs_utils.getAllPackages(ocsClient, (err, res) => { if (err) { - DdUtils.errorAndExit(`Error making request to OCS: ${err}`); + DdLogger.errorAndExit(`Error making request to OCS: ${err}`); } const t = new Table(); diff --git a/src/ddrv-subscribe.js b/src/ddrv-subscribe.js index a8dfb64..60c6820 100644 --- a/src/ddrv-subscribe.js +++ b/src/ddrv-subscribe.js @@ -24,32 +24,14 @@ const fs = require("fs"); const util = require("util"); const path = require("path"); -const moment = require("moment"); -const { FileMetadata } = require("./core/DdFileMetadata.js"); const { Command, Option } = require("commander"); const program = new Command(); const Validator = require("jsonschema").Validator; //local imports const DdConsts = require("./core/DdConstants.js"); -const DdUtils = require("./core/DdUtils.js"); -const { DataDriveWsClient } = require("./core/DdWsClient.js"); -const DdSubConfig = require("./core/DdSubConfig.js"); -const DdOptions = require("./core/DdOptions.js"); const DdLogger = require("./core/DdLogger.js").logger; -const { - DataDriveMWServiceSettings, -} = require("./core/DataDriveMWServiceSettings"); -const { Processor, Queue } = require("./core/DdQueue.js"); -const { - QueueEmptyError, - MaxProcessSizeError, - CannotWriteToLocalFileError, -} = require("./core/DdError.js"); -const DdPluginHandler = require("./core/DdPluginHandler.js").PluginHandler; -const { EmptyPromise } = require("./core/EmptyPromise"); const config = require("./core/config.js").config; -const SsoToken = require("./core/SsoToken.js"); const utils = require("./core/utils.js"); const ocs_utils = require("./core/ocs_utils.js"); const ws_utils = require("./core/websocket_utils.js"); @@ -151,7 +133,7 @@ function validateOptions(options = {}) { if (errors.length) { const outMsg = errors.join("\n"); - return DdUtils.errorAndExit(outMsg); + return DdLogger.errorAndExit(outMsg); } return options; @@ -167,13 +149,13 @@ function getArgs() { .addOption( new Option( "-f, --filter [value]", - "A wildcard expression to filter files based on OCS Full Name.", + "A wildcard expression to filter files by filename. (See '-if' option to apply this filter to the full file path.)", ).conflicts("regex"), ) .addOption( new Option( "-x, --regex [value]", - "A regex expression to filter files based on OCS Full Name. Please reference https://www.elastic.co/guide/en/elasticsearch/reference/6.4/query-dsl-regexp-query.html#regexp-syntax and NodeJS RegExp.", + "A regex expression to filter files by filename. (See '-if' option to apply this filter to the full file path.) Please reference https://www.elastic.co/guide/en/elasticsearch/reference/6.4/query-dsl-regexp-query.html#regexp-syntax and NodeJS RegExp.", ).conflicts("filter"), ) .option( @@ -190,7 +172,7 @@ function getArgs() { ) .option( "-if, --include-full-path", - "If filter and regex expressions include only the name or the full path. defaulted to `NO`.", + "Filters and regexps will be applied the entire file path.", ) .option( "-O, --overwrite", @@ -215,7 +197,8 @@ function getArgs() { .option( "--log-date-pattern [log-date-pattern]", "Turns on log rolling using the specified format. Options are: monthly, weekly, daily. This option can also accept a custom format (more info: https://momentjs.com/docs/#/displaying/format/). This format will define the frequency of the log rotation, with the logs rotating on the smallest date/time increment specified in the format.", - ); + ) + .option("--callback [callback]", "File download callback command. This is executed after each file download. It should be enclosed in single-quotes and may use the following special variables: $FILENAME $SRC_PATH $DEST_PATH. For example, ddrv subscribe -p sample-package -o output_folder --callback 'echo $FILENAME $SRC_PATH $DEST_PATH'"); program.parse(); return validateOptions(program.opts()); @@ -437,7 +420,7 @@ async function downloadFileAndUpdateCheckpoint(ocsClient, options, fileData) { ocsClient, fileData, destPath, - options.overwrite, + options, ); break; } catch (e) { @@ -525,7 +508,7 @@ async function verifyOutputPath(options) { } } if (errMsg) { - DdUtils.errorAndExit(errMsg); + DdLogger.errorAndExit(errMsg); } } } @@ -577,14 +560,14 @@ async function main() { try { new RegExp(options.regex); } catch (e) { - DdUtils.errorAndExit( + DdLogger.errorAndExit( `Regexp ${options.regex} is not a valid regular expression.`, ); } } if (options.savedSearchName && options.packageName) { - DdUtils.errorAndExit( + DdLogger.errorAndExit( "Both a saved search and a package have been specified. Please choose only one", ); } @@ -596,7 +579,9 @@ async function main() { options.packageName, ); if (!packageInfo) { - DdUtils.errorAndExit(`Cannot find package: ${options.packageName}`); + DdLogger.errorAndExit( + `Cannot find package: ${options.packageName}`, + ); } options.packageInfo = packageInfo; } else if (options.savedSearchName) { @@ -606,7 +591,7 @@ async function main() { try { ocs_utils.getSavedSearchInfo(ocsClient, options.savedSearchName); } catch (e) { - DdUtils.errorAndExit(e.message); + DdLogger.errorAndExit(e.message); } } diff --git a/src/ddrv.js b/src/ddrv.js index a965439..b459d53 100644 --- a/src/ddrv.js +++ b/src/ddrv.js @@ -13,5 +13,6 @@ program.command("config", "Configure CLI"); program.command("subscribe [parameters]", "subscribe to an OCS package."); program.command("publish [parameters]", "publish to an OCS package."); program.command("show ", "display one or many OCS resources."); +program.command("license", "Show software license."); program.parse(); diff --git a/src/package-lock.json b/src/package-lock.json index 1015c73..fd66a8b 100644 --- a/src/package-lock.json +++ b/src/package-lock.json @@ -1,37 +1,28 @@ { "name": "ddrv_cli", - "version": "2.0.1", + "version": "2.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ddrv_cli", - "version": "2.0.1", - "license": "UNLICENSED", + "version": "2.0.5", + "license": "Caltech", "dependencies": { "@gov.nasa.jpl.ammos.ids/mdms-aocs-js-client": "1.1", - "@gov.nasa.jpl.m2020.cs3/ocs-js-client": "~7.6.0", - "axios": "~0.18.1", - "axios-debug": "0.0.4", - "bluebird": "^3.5.2", + "@gov.nasa.jpl.m2020.cs3/ocs-js-client": "^9.0.1", "chai": "~4.2.0", "chokidar": "^3.6.0", "commander": "^11.1.0", - "cookie": "~0.3.1", - "dotenv": "~7.0.0", "easy-table": "~1.1.1", "form-data": "^4.0.0", "fs-extra": "~8.1.0", - "glob-to-regexp": "~0.4.1", "jsonschema": "^1.4.1", - "lodash": "~4.17.15", - "mocha": "~6.2.0", + "minimist": "^1.2.8", "moment": "~2.24.0", "node-fetch": "^2.7.0", "pkg": "^5.1.0", - "request": "~2.88.2", "shelljs": "~0.8.3", - "upath": "~1.1.2", "winston": "~3.2.1", "winston-daily-rotate-file": "^5.0.0", "ws": "~6.2.1" @@ -306,56 +297,73 @@ } }, "node_modules/@gov.nasa.jpl.m2020.cs3/ocs-js-client": { - "version": "7.6.0", - "resolved": "https://artifactory.jpl.nasa.gov:443/artifactory/api/npm/npm-release-local/@gov.nasa.jpl.m2020.cs3/ocs-js-client/-/@gov.nasa.jpl.m2020.cs3/ocs-js-client-7.6.0.tgz", - "integrity": "sha512-3xQn4W41yK5NK6ckolW48dUob/zycIj2YBKhSmJlT+0GZMiuSnjQzIR8NYnUZM8iN48jmKvRbGwKQJlKY+Ng3Q==", + "version": "9.0.1", + "resolved": "https://artifactory.jpl.nasa.gov:443/artifactory/api/npm/npm-release-local/@gov.nasa.jpl.m2020.cs3/ocs-js-client/-/@gov.nasa.jpl.m2020.cs3/ocs-js-client-9.0.1.tgz", + "integrity": "sha512-OqhKDHvI4jYTwC1BIZECKBu9qdMaDi/+IMVYANs3GVZvWEyBwvCC4NLmLVKPZbD4KLgYkqu2p5f2mYb4SreKBA==", "bundleDependencies": [ "ajv", - "ajv" + "ajv-formats", + "fastq", + "http-status-codes", + "https-proxy-agent" ], "hasInstallScript": true, "dependencies": { - "ajv": "^8.11.0", + "ajv": "^8.12.0", "ajv-formats": "^2.1.1", - "fastq": "^1.13.0", + "fastq": "^1.15.0", "http-status-codes": "^2.2.0", - "https-proxy-agent": "^5.0.1", - "moment": "^2.29.4", - "through": "^2.3.8" + "https-proxy-agent": "^7.0.4" } }, "node_modules/@gov.nasa.jpl.m2020.cs3/ocs-js-client/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.1", + "inBundle": true, + "license": "MIT", "dependencies": { - "debug": "4" + "debug": "^4.3.4" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/@gov.nasa.jpl.m2020.cs3/ocs-js-client/node_modules/ajv": { - "version": "8.11.2", + "version": "8.17.1", "inBundle": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/@gov.nasa.jpl.m2020.cs3/ocs-js-client/node_modules/ajv-formats": { + "version": "2.1.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/@gov.nasa.jpl.m2020.cs3/ocs-js-client/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.7", + "inBundle": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -371,16 +379,34 @@ "inBundle": true, "license": "MIT" }, + "node_modules/@gov.nasa.jpl.m2020.cs3/ocs-js-client/node_modules/fast-uri": { + "version": "3.0.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/@gov.nasa.jpl.m2020.cs3/ocs-js-client/node_modules/fastq": { + "version": "1.17.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/@gov.nasa.jpl.m2020.cs3/ocs-js-client/node_modules/http-status-codes": { + "version": "2.3.0", + "inBundle": true, + "license": "MIT" + }, "node_modules/@gov.nasa.jpl.m2020.cs3/ocs-js-client/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "version": "7.0.5", + "inBundle": true, + "license": "MIT", "dependencies": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/@gov.nasa.jpl.m2020.cs3/ocs-js-client/node_modules/json-schema-traverse": { @@ -388,21 +414,10 @@ "inBundle": true, "license": "MIT" }, - "node_modules/@gov.nasa.jpl.m2020.cs3/ocs-js-client/node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", - "engines": { - "node": "*" - } - }, - "node_modules/@gov.nasa.jpl.m2020.cs3/ocs-js-client/node_modules/punycode": { - "version": "2.1.1", + "node_modules/@gov.nasa.jpl.m2020.cs3/ocs-js-client/node_modules/ms": { + "version": "2.1.3", "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } + "license": "MIT" }, "node_modules/@gov.nasa.jpl.m2020.cs3/ocs-js-client/node_modules/require-from-string": { "version": "2.0.2", @@ -412,12 +427,13 @@ "node": ">=0.10.0" } }, - "node_modules/@gov.nasa.jpl.m2020.cs3/ocs-js-client/node_modules/uri-js": { - "version": "4.4.1", + "node_modules/@gov.nasa.jpl.m2020.cs3/ocs-js-client/node_modules/reusify": { + "version": "1.0.4", "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, "node_modules/@jridgewell/gen-mapping": { @@ -1477,14 +1493,6 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, - "node_modules/ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "engines": { - "node": ">=6" - } - }, "node_modules/ansi-escapes": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", @@ -1497,22 +1505,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ansicolors": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", @@ -1531,14 +1523,6 @@ "node": ">= 8" } }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/argv-formatter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/argv-formatter/-/argv-formatter-1.0.0.tgz", @@ -1568,19 +1552,6 @@ "node": ">=0.10.0" } }, - "node_modules/asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "engines": { - "node": ">=0.8" - } - }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -1605,7 +1576,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/at-least-node": { "version": "1.0.0", @@ -1615,37 +1586,6 @@ "node": ">= 4.0.0" } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" - }, - "node_modules/axios": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", - "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", - "deprecated": "Critical security vulnerability fixed in v0.21.1. For more information, see https://github.com/axios/axios/pull/3410", - "dependencies": { - "follow-redirects": "1.5.10", - "is-buffer": "^2.0.2" - } - }, - "node_modules/axios-debug": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/axios-debug/-/axios-debug-0.0.4.tgz", - "integrity": "sha1-Ri+vl++Eoij1K29vdNmWG9z95OI=", - "dependencies": { - "chalk": "^1.1.3" - } - }, "node_modules/balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -1670,14 +1610,6 @@ } ] }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, "node_modules/before-after-hook": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", @@ -1715,11 +1647,6 @@ "node": ">= 6" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, "node_modules/bottleneck": { "version": "2.19.5", "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", @@ -1746,11 +1673,6 @@ "node": ">=8" } }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" - }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -1787,6 +1709,7 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, "engines": { "node": ">=6" } @@ -1821,11 +1744,6 @@ "cdl": "bin/cdl.js" } }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, "node_modules/chai": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", @@ -1842,29 +1760,6 @@ "node": ">=4" } }, - "node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/chalk/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -1982,48 +1877,6 @@ "node": ">=8" } }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", @@ -2080,7 +1933,7 @@ }, "node_modules/combined-stream": { "version": "1.0.8", - "resolved": "https://artifactory.jpl.nasa.gov:443/artifactory/api/npm/npm-develop-virtual/combined-stream/-/combined-stream-1.0.8.tgz", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dependencies": { "delayed-stream": "~1.0.0" @@ -2222,14 +2075,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -2353,17 +2198,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", @@ -2373,23 +2207,11 @@ "node": "*" } }, - "node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -2461,21 +2283,10 @@ "clone": "^1.0.2" } }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "engines": { "node": ">=0.4.0" } @@ -2504,14 +2315,6 @@ "kuler": "1.0.x" } }, - "node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -2535,14 +2338,6 @@ "node": ">=8" } }, - "node_modules/dotenv": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz", - "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==", - "engines": { - "node": ">=6" - } - }, "node_modules/duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", @@ -2571,20 +2366,6 @@ "node": ">=4" } }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, "node_modules/enabled": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", @@ -2756,46 +2537,6 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, - "node_modules/es-abstract": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", - "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", - "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/escalade": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", @@ -2820,6 +2561,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -2883,24 +2625,6 @@ "node": ">=6" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" - }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -2916,11 +2640,6 @@ "node": ">=8.6.0" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -2977,17 +2696,6 @@ "node": ">=8" } }, - "node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/find-versions": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-5.1.0.tgz", @@ -3003,40 +2711,9 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "deprecated": "Fixed a prototype pollution security issue in 4.1.0, please upgrade to ^4.1.1 or ^5.0.1.", - "dependencies": { - "is-buffer": "~2.0.3" - }, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "dependencies": { - "debug": "=3.1.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "engines": { - "node": "*" - } - }, "node_modules/form-data": { "version": "4.0.0", - "resolved": "https://artifactory.jpl.nasa.gov:443/artifactory/api/npm/npm-develop-virtual/form-data/-/form-data-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dependencies": { "asynckit": "^0.4.0", @@ -3133,14 +2810,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/git-log-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz", @@ -3196,11 +2865,6 @@ "node": ">= 6" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" - }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -3225,14 +2889,6 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==" }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "engines": { - "node": ">=4.x" - } - }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -3254,47 +2910,6 @@ "uglify-js": "^3.1.4" } }, - "node_modules/handlebars/node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/har-validator/node_modules/ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dependencies": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "node_modules/hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", @@ -3315,36 +2930,15 @@ "node": ">= 0.4.0" } }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, "engines": { "node": ">=4" } }, - "node_modules/has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -3356,14 +2950,6 @@ "node": ">= 0.4" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" - } - }, "node_modules/hook-std": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-3.0.0.tgz", @@ -3418,20 +3004,6 @@ } } }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/http-status-codes": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.2.0.tgz", @@ -3612,25 +3184,6 @@ "node": ">=8" } }, - "node_modules/is-buffer": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", - "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-core-module": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", @@ -3642,17 +3195,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3661,14 +3203,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "engines": { - "node": ">=4" - } - }, "node_modules/is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -3706,20 +3240,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dependencies": { - "has": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -3728,20 +3248,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-text-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", @@ -3754,11 +3260,6 @@ "node": ">=8" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, "node_modules/is-unicode-supported": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", @@ -3779,12 +3280,8 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true }, "node_modules/issue-parser": { "version": "6.0.0", @@ -3817,23 +3314,6 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -3857,20 +3337,11 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "node_modules/json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true }, "node_modules/jsonfile": { "version": "4.0.0", @@ -3913,20 +3384,6 @@ "node": "*" } }, - "node_modules/jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -3974,18 +3431,6 @@ "node": ">=4" } }, - "node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -4033,60 +3478,6 @@ "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", "dev": true }, - "node_modules/log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dependencies": { - "chalk": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-symbols/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/logform": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", @@ -4378,19 +3769,19 @@ } }, "node_modules/mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "mime-db": "1.40.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" @@ -4437,9 +3828,12 @@ } }, "node_modules/minimist": { - "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/minimist-options": { "version": "4.1.0", @@ -4455,93 +3849,11 @@ "node": ">= 6" } }, - "node_modules/mkdirp": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", - "dependencies": { - "minimist": "0.0.8" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, - "node_modules/mocha": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.2.tgz", - "integrity": "sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A==", - "dependencies": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.0", - "yargs-parser": "13.1.1", - "yargs-unparser": "1.6.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/mocha/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/modify-values": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", @@ -4651,15 +3963,6 @@ "lodash": "^4.17.21" } }, - "node_modules/node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dependencies": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } - }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -8029,14 +7332,6 @@ "inBundle": true, "license": "ISC" }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, "node_modules/object-hash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", @@ -8045,51 +7340,6 @@ "node": ">= 6" } }, - "node_modules/object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -8157,6 +7407,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -8164,17 +7415,6 @@ "node": ">=6" } }, - "node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/p-map": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.2.tgz", @@ -8200,6 +7440,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, "engines": { "node": ">=6" } @@ -8233,6 +7474,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, "engines": { "node": ">=4" } @@ -8275,11 +7517,6 @@ "node": "*" } }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, "node_modules/picocolors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", @@ -8762,14 +7999,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/pkg/node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/pkg/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -8814,14 +8043,6 @@ "node": ">=10" } }, - "node_modules/prebuild-install/node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -8841,11 +8062,6 @@ "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", "dev": true }, - "node_modules/psl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz", - "integrity": "sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA==" - }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -8873,14 +8089,6 @@ "teleport": ">=0.2.0" } }, - "node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "engines": { - "node": ">=0.6" - } - }, "node_modules/quick-lru": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", @@ -8904,11 +8112,6 @@ "rc": "cli.js" } }, - "node_modules/rc/node_modules/minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - }, "node_modules/read-pkg": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-8.1.0.tgz", @@ -9215,50 +8418,6 @@ "node": ">=14" } }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -9275,11 +8434,6 @@ "node": ">=0.10.0" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" - }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -9343,11 +8497,6 @@ "node": ">=10" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, "node_modules/semantic-release": { "version": "21.1.2", "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-21.1.2.tgz", @@ -9794,6 +8943,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true, "bin": { "semver": "bin/semver" } @@ -9837,11 +8987,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -10085,35 +9230,6 @@ "node": ">= 10.x" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -10153,78 +9269,6 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "engines": { - "node": ">=4" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/string.prototype.trimleft": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", - "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", - "dependencies": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimright": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", - "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", - "dependencies": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -10263,14 +9307,6 @@ "node": ">=0.10.0" } }, - "node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/supports-hyperlinks": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", @@ -10457,18 +9493,6 @@ "node": ">=8.0" } }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -10508,11 +9532,6 @@ "node": "*" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -10587,15 +9606,6 @@ "node": ">= 4.0.0" } }, - "node_modules/upath": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", - "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", - "engines": { - "node": ">=4", - "yarn": "*" - } - }, "node_modules/uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -10618,15 +9628,6 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, - "node_modules/uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -10637,19 +9638,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", @@ -10673,30 +9661,6 @@ "webidl-conversions": "^3.0.0" } }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, "node_modules/winston": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz", @@ -10778,62 +9742,6 @@ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "dev": true }, - "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -10856,87 +9764,11 @@ "node": ">=0.4" } }, - "node_modules/y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" - }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, - "node_modules/yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" - } - }, - "node_modules/yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", - "dependencies": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/yocto-queue": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", diff --git a/src/package.json b/src/package.json index a987b43..871a43f 100644 --- a/src/package.json +++ b/src/package.json @@ -7,28 +7,19 @@ }, "dependencies": { "@gov.nasa.jpl.ammos.ids/mdms-aocs-js-client": "1.1", - "@gov.nasa.jpl.m2020.cs3/ocs-js-client": "~7.6.0", - "axios": "~0.18.1", - "axios-debug": "0.0.4", - "bluebird": "^3.5.2", + "@gov.nasa.jpl.m2020.cs3/ocs-js-client": "^9.0.1", "chai": "~4.2.0", "chokidar": "^3.6.0", "commander": "^11.1.0", - "cookie": "~0.3.1", - "dotenv": "~7.0.0", "easy-table": "~1.1.1", "form-data": "^4.0.0", "fs-extra": "~8.1.0", - "glob-to-regexp": "~0.4.1", "jsonschema": "^1.4.1", - "lodash": "~4.17.15", - "mocha": "~6.2.0", + "minimist": "^1.2.8", "moment": "~2.24.0", "node-fetch": "^2.7.0", "pkg": "^5.1.0", - "request": "~2.88.2", "shelljs": "~0.8.3", - "upath": "~1.1.2", "winston": "~3.2.1", "winston-daily-rotate-file": "^5.0.0", "ws": "~6.2.1" @@ -142,7 +133,7 @@ "OCS", "subscribe" ], - "author": "Nicholas Toole", - "license": "UNLICENSED", - "version": "2.0.1" + "author": "Joshua Rodriguez", + "license": "Caltech", + "version": "2.0.5" }