* Issue #96: Migrate Node Utils to Separate Repo * Updated gradle dependencies, retested builds
This commit is contained in:
parent
9181ef192d
commit
e33ff98a61
31
build.gradle
31
build.gradle
|
@ -21,12 +21,12 @@ repositories {
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'com.google.guava:guava:30.1.1-jre'
|
compile 'com.google.guava:guava:30.1.1-jre'
|
||||||
compile 'com.google.inject:guice:5.0.1'
|
compile 'com.google.inject:guice:5.0.1'
|
||||||
compile 'commons-cli:commons-cli:1.4'
|
compile 'commons-cli:commons-cli:1.5.0'
|
||||||
|
|
||||||
compile 'org.apache.logging.log4j:log4j-api:2.13.0'
|
compile 'org.apache.logging.log4j:log4j-api:2.17.0'
|
||||||
compile 'org.apache.logging.log4j:log4j-slf4j-impl:2.13.0'
|
compile 'org.apache.logging.log4j:log4j-slf4j-impl:2.17.0'
|
||||||
compile 'org.apache.logging.log4j:log4j-1.2-api:2.13.0'
|
compile 'org.apache.logging.log4j:log4j-1.2-api:2.17.0'
|
||||||
compile 'org.apache.logging.log4j:log4j-core:2.13.0'
|
compile 'org.apache.logging.log4j:log4j-core:2.17.0'
|
||||||
|
|
||||||
compile 'org.apache.olingo:odata-client-api:4.8.0'
|
compile 'org.apache.olingo:odata-client-api:4.8.0'
|
||||||
compile 'org.apache.olingo:odata-commons-core:4.8.0'
|
compile 'org.apache.olingo:odata-commons-core:4.8.0'
|
||||||
|
@ -35,19 +35,19 @@ dependencies {
|
||||||
compile 'org.apache.poi:poi:5.0.0'
|
compile 'org.apache.poi:poi:5.0.0'
|
||||||
compile 'org.apache.poi:poi-ooxml:5.0.0'
|
compile 'org.apache.poi:poi-ooxml:5.0.0'
|
||||||
|
|
||||||
compile 'io.rest-assured:rest-assured:4.3.3'
|
compile 'io.rest-assured:rest-assured:4.4.0'
|
||||||
compile 'io.rest-assured:json-path:4.3.3'
|
compile 'io.rest-assured:json-path:4.4.0'
|
||||||
compile 'io.rest-assured:json-schema-validator:4.3.3'
|
compile 'io.rest-assured:json-schema-validator:4.4.0'
|
||||||
|
|
||||||
compile 'io.cucumber:cucumber-java8:6.10.2'
|
compile 'io.cucumber:cucumber-java8:7.1.0'
|
||||||
compile 'io.cucumber:cucumber-java:6.10.2'
|
compile 'io.cucumber:cucumber-java:7.1.0'
|
||||||
compile 'io.cucumber:cucumber-junit:6.10.2'
|
compile 'io.cucumber:cucumber-junit:7.1.0'
|
||||||
compile 'io.cucumber:cucumber-guice:6.10.2'
|
compile 'io.cucumber:cucumber-guice:7.1.0'
|
||||||
compile 'io.cucumber:cucumber-core:6.10.2'
|
compile 'io.cucumber:cucumber-core:7.1.0'
|
||||||
|
|
||||||
//TODO: choose one schema validator between this and rest-assured
|
//TODO: choose one schema validator between this and rest-assured
|
||||||
compile 'com.networknt:json-schema-validator:1.0.51'
|
compile 'com.networknt:json-schema-validator:1.0.63'
|
||||||
compile 'com.google.code.gson:gson:2.8.6'
|
compile 'com.google.code.gson:gson:2.8.9'
|
||||||
compile 'org.apache.commons:commons-text:1.9'
|
compile 'org.apache.commons:commons-text:1.9'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,6 @@ task testWebApiCore_2_0_0() {
|
||||||
systemProperties = System.getProperties()
|
systemProperties = System.getProperties()
|
||||||
|
|
||||||
args = [
|
args = [
|
||||||
'--strict',
|
|
||||||
'--plugin',
|
'--plugin',
|
||||||
'pretty',
|
'pretty',
|
||||||
'--plugin',
|
'--plugin',
|
||||||
|
|
|
@ -1,118 +0,0 @@
|
||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
.pnpm-debug.log*
|
|
||||||
|
|
||||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
||||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
|
||||||
|
|
||||||
# Runtime data
|
|
||||||
pids
|
|
||||||
*.pid
|
|
||||||
*.seed
|
|
||||||
*.pid.lock
|
|
||||||
|
|
||||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
||||||
lib-cov
|
|
||||||
|
|
||||||
# Coverage directory used by tools like istanbul
|
|
||||||
coverage
|
|
||||||
*.lcov
|
|
||||||
|
|
||||||
# nyc test coverage
|
|
||||||
.nyc_output
|
|
||||||
|
|
||||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
||||||
.grunt
|
|
||||||
|
|
||||||
# Bower dependency directory (https://bower.io/)
|
|
||||||
bower_components
|
|
||||||
|
|
||||||
# node-waf configuration
|
|
||||||
.lock-wscript
|
|
||||||
|
|
||||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
||||||
build/Release
|
|
||||||
|
|
||||||
# Dependency directories
|
|
||||||
node_modules/
|
|
||||||
jspm_packages/
|
|
||||||
|
|
||||||
# Snowpack dependency directory (https://snowpack.dev/)
|
|
||||||
web_modules/
|
|
||||||
|
|
||||||
# TypeScript cache
|
|
||||||
*.tsbuildinfo
|
|
||||||
|
|
||||||
# Optional npm cache directory
|
|
||||||
.npm
|
|
||||||
|
|
||||||
# Optional eslint cache
|
|
||||||
.eslintcache
|
|
||||||
|
|
||||||
# Microbundle cache
|
|
||||||
.rpt2_cache/
|
|
||||||
.rts2_cache_cjs/
|
|
||||||
.rts2_cache_es/
|
|
||||||
.rts2_cache_umd/
|
|
||||||
|
|
||||||
# Optional REPL history
|
|
||||||
.node_repl_history
|
|
||||||
|
|
||||||
# Output of 'npm pack'
|
|
||||||
*.tgz
|
|
||||||
|
|
||||||
# Yarn Integrity file
|
|
||||||
.yarn-integrity
|
|
||||||
|
|
||||||
# dotenv environment variables file
|
|
||||||
.env
|
|
||||||
.env.test
|
|
||||||
.env.production
|
|
||||||
|
|
||||||
# parcel-bundler cache (https://parceljs.org/)
|
|
||||||
.cache
|
|
||||||
.parcel-cache
|
|
||||||
|
|
||||||
# Next.js build output
|
|
||||||
.next
|
|
||||||
out
|
|
||||||
|
|
||||||
# Nuxt.js build / generate output
|
|
||||||
.nuxt
|
|
||||||
dist
|
|
||||||
|
|
||||||
# Gatsby files
|
|
||||||
.cache/
|
|
||||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
|
||||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
|
||||||
# public
|
|
||||||
|
|
||||||
# vuepress build output
|
|
||||||
.vuepress/dist
|
|
||||||
|
|
||||||
# Serverless directories
|
|
||||||
.serverless/
|
|
||||||
|
|
||||||
# FuseBox cache
|
|
||||||
.fusebox/
|
|
||||||
|
|
||||||
# DynamoDB Local files
|
|
||||||
.dynamodb/
|
|
||||||
|
|
||||||
# TernJS port file
|
|
||||||
.tern-port
|
|
||||||
|
|
||||||
# Stores VSCode versions used for testing VSCode extensions
|
|
||||||
.vscode-test
|
|
||||||
|
|
||||||
# yarn v2
|
|
||||||
.yarn/cache
|
|
||||||
.yarn/unplugged
|
|
||||||
.yarn/build-state.yml
|
|
||||||
.yarn/install-state.gz
|
|
||||||
.pnp.*
|
|
|
@ -1,193 +0,0 @@
|
||||||
const fs = require('fs');
|
|
||||||
const fse = require('fs-extra');
|
|
||||||
const { execSync } = require('child_process');
|
|
||||||
|
|
||||||
//parse command line args
|
|
||||||
const yargs = require('yargs/yargs');
|
|
||||||
const { hideBin } = require('yargs/helpers');
|
|
||||||
const argv = yargs(hideBin(process.argv)).argv;
|
|
||||||
|
|
||||||
const { processDataDictionaryResults } = require('./services/postResultsToApi.js');
|
|
||||||
const { processDataAvailabilityReport } = require('./services/processDataAvailabilityReport.js');
|
|
||||||
|
|
||||||
const { COMMANDER_PATH } = require('./batch-config.json');
|
|
||||||
const CERTIFICATION_RESULTS_PATH = `${COMMANDER_PATH}/build/certification`;
|
|
||||||
|
|
||||||
const buildRecipientPath = (providerUoi, recipientUoi) => {
|
|
||||||
if (!providerUoi) throw Error('providerUoi is required!');
|
|
||||||
if (!recipientUoi) throw Error('recipientUoi is required!');
|
|
||||||
|
|
||||||
return `${providerUoi}/${recipientUoi}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const createResoscriptBearerTokenConfig = ({uri, token} = config) => '<?xml version="1.0" encoding="utf-8" ?>' +
|
|
||||||
'<OutputScript>' +
|
|
||||||
' <ClientSettings>' +
|
|
||||||
` <WebAPIURI>${uri}</WebAPIURI>` +
|
|
||||||
' <AuthenticationType>authorization_code</AuthenticationType>' +
|
|
||||||
` <BearerToken>${token}</BearerToken>` +
|
|
||||||
' </ClientSettings>' +
|
|
||||||
'</OutputScript>';
|
|
||||||
|
|
||||||
const createResoscriptClientCredentialsConfig = ( { uri, clientCredentials } = config) => '<?xml version="1.0" encoding="utf-8" ?>' +
|
|
||||||
'<OutputScript>' +
|
|
||||||
' <ClientSettings>' +
|
|
||||||
` <WebAPIURI>${uri}</WebAPIURI>` +
|
|
||||||
' <AuthenticationType>client_credentials</AuthenticationType>' +
|
|
||||||
` <ClientIdentification>${clientCredentials.clientId}</ClientIdentification>` +
|
|
||||||
` <ClientSecret>${clientCredentials.clientSecret}</ClientSecret>` +
|
|
||||||
` <TokenURI>${clientCredentials.tokenUri}</TokenURI>` +
|
|
||||||
` ${clientCredentials.scope ? '<ClientScope>' + clientCredentials.scope + '</ClientScope>': ''}` +
|
|
||||||
' </ClientSettings>' +
|
|
||||||
'</OutputScript>';
|
|
||||||
|
|
||||||
const isClientCredentalsConfig = ( config = { clientCredentials: {} } ) => config.clientCredentials
|
|
||||||
&& config.clientCredentials.clientId
|
|
||||||
&& config.clientCredentials.clientSecret
|
|
||||||
&& config.clientCredentials.tokenUri;
|
|
||||||
|
|
||||||
const isBearerTokenConfig = ( config = { token: '' } ) => !!config.token;
|
|
||||||
|
|
||||||
const buildResoscript = (config={}) => {
|
|
||||||
if (isClientCredentalsConfig(config)) {
|
|
||||||
return createResoscriptClientCredentialsConfig(config);
|
|
||||||
} else if (isBearerTokenConfig(config)) {
|
|
||||||
return createResoscriptBearerTokenConfig(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const runTests = async jsonConfigPath => {
|
|
||||||
if (!jsonConfigPath) throw Error("Missing jsonConfigPath.");
|
|
||||||
|
|
||||||
try {
|
|
||||||
providerInfo = JSON.parse(fs.readFileSync(jsonConfigPath));
|
|
||||||
} catch (err) {
|
|
||||||
throw new Error('Could not read provider info!');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const { providerUoi, configs } = providerInfo;
|
|
||||||
|
|
||||||
if (!providerUoi) throw new Error('providerUoi is required!');
|
|
||||||
if (!configs || !configs.length) throw new Error('configs must contain valid configurations');
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (fs.existsSync(providerUoi)) {
|
|
||||||
try {
|
|
||||||
fs.renameSync(providerUoi, `${providerUoi}-old-${Date.now()}`);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
throw new Error('Could not rename directory! Exiting!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//create root directory
|
|
||||||
fs.mkdirSync(providerUoi);
|
|
||||||
|
|
||||||
const totalTestCount = configs.length;
|
|
||||||
let failedTestCount = 0;
|
|
||||||
|
|
||||||
configs.forEach(config => {
|
|
||||||
|
|
||||||
const
|
|
||||||
RECIPIENT_PATH = buildRecipientPath(providerUoi, config.recipientUoi),
|
|
||||||
RESOSCRIPT_CONFIG = buildResoscript(config),
|
|
||||||
CONFIG_PATH = `${COMMANDER_PATH}/${RECIPIENT_PATH}/config.xml`;
|
|
||||||
|
|
||||||
if (!RESOSCRIPT_CONFIG) throw new Error('There was a problem creating a RESOScript config for recipientUoi: ' + config.recipientUoi);
|
|
||||||
|
|
||||||
//create recipient directory
|
|
||||||
fs.mkdirSync(RECIPIENT_PATH);
|
|
||||||
fs.writeFileSync(CONFIG_PATH, RESOSCRIPT_CONFIG);
|
|
||||||
|
|
||||||
//run dd tests
|
|
||||||
const dataDictionaryResult = execSync(`${COMMANDER_PATH}/gradlew testDataDictionary_1_7 -DpathToRESOScript='${CONFIG_PATH}'`,
|
|
||||||
{ stdio: ['inherit', 'inherit', 'pipe'] });
|
|
||||||
|
|
||||||
if (dataDictionaryResult && dataDictionaryResult.stderr) {
|
|
||||||
console.error('Data Dictionary testing failed for recipientUoi: ' + config.recipientUoi);
|
|
||||||
console.error(Error(dataDictionaryResult.stderr));
|
|
||||||
|
|
||||||
//TODO, create error directory with each corresponding log
|
|
||||||
process.exitCode = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//run data availability tests
|
|
||||||
const dataAvailabilityResult = execSync(`${COMMANDER_PATH}/gradlew testDataAvailability_1_7 -DpathToRESOScript='${CONFIG_PATH}'`,
|
|
||||||
{ stdio: ['inherit', 'inherit', 'pipe'] });
|
|
||||||
|
|
||||||
|
|
||||||
if (dataAvailabilityResult && dataAvailabilityResult.stderr) {
|
|
||||||
console.error('Data Dictionary testing failed for recipientUoi: ' + config.recipientUoi);
|
|
||||||
console.error(Error(dataAvailabilityResult.stderr));
|
|
||||||
process.exitCode = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const paths = ['results', 'reports', 'cucumberJson'];
|
|
||||||
paths.forEach(path => {
|
|
||||||
fse.copySync(`${CERTIFICATION_RESULTS_PATH}/${path}`, RECIPIENT_PATH, { overwrite: true }, err => {
|
|
||||||
if (err) {
|
|
||||||
console.error(err);
|
|
||||||
} else {
|
|
||||||
console.log(`Copied ${path} to ${RECIPIENT_PATH}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log("Testing complete! Tests passed: " + totalTestCount);
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const processDDResult = async (providerUoi, recipientUoi) =>
|
|
||||||
await processDataDictionaryResults(providerUoi, recipientUoi, buildRecipientPath(providerUoi, recipientUoi));
|
|
||||||
|
|
||||||
|
|
||||||
// const cliHandler = argv => {
|
|
||||||
// argv.command({
|
|
||||||
// command: "action",
|
|
||||||
// description: "top level command",
|
|
||||||
// builder: {
|
|
||||||
// command: "bar",
|
|
||||||
// description: "child command of foo",
|
|
||||||
// builder: function() {
|
|
||||||
// console.log("builder barr!");
|
|
||||||
// },
|
|
||||||
// handler: a => {
|
|
||||||
// console.log("handler barr!");
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// handler: args => {
|
|
||||||
// console.log("handler foo!");
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// .demand(1, "must provide a valid command")
|
|
||||||
// .help("h")
|
|
||||||
// .alias("h", "help")
|
|
||||||
// .argv
|
|
||||||
|
|
||||||
// if (runTests) {
|
|
||||||
// const { configFilePath } = argv;
|
|
||||||
|
|
||||||
// if (!configFilePath) console.log('configFilePath is required!\nUsage: $ node . --runTests');
|
|
||||||
|
|
||||||
// } else if (processDDResult) {
|
|
||||||
|
|
||||||
// } else if (dataAvailabilityEtl) {
|
|
||||||
|
|
||||||
// } else {
|
|
||||||
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
runTests,
|
|
||||||
processDDResult,
|
|
||||||
processDataAvailabilityReport
|
|
||||||
};
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"API_KEY": "",
|
|
||||||
"COMMANDER_PATH": ""
|
|
||||||
}
|
|
|
@ -1,616 +0,0 @@
|
||||||
{
|
|
||||||
"name": "runResoscripts",
|
|
||||||
"lockfileVersion": 2,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"dependencies": {
|
|
||||||
"aws-sdk": "^2.1026.0",
|
|
||||||
"axios": "^0.24.0",
|
|
||||||
"fs-extra": "^10.0.0",
|
|
||||||
"yargs": "^17.3.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ansi-regex": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ansi-styles": {
|
|
||||||
"version": "4.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
|
||||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
|
||||||
"dependencies": {
|
|
||||||
"color-convert": "^2.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/aws-sdk": {
|
|
||||||
"version": "2.1027.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1027.0.tgz",
|
|
||||||
"integrity": "sha512-j3UjPV9hzyCvkmfcbhRscMggdmrPqlhvo8QzkXCGFfPXjZMh1OJd4HkCEH2NaunzLOyF2Y3QzxKrGOLMT7sNzg==",
|
|
||||||
"dependencies": {
|
|
||||||
"buffer": "4.9.2",
|
|
||||||
"events": "1.1.1",
|
|
||||||
"ieee754": "1.1.13",
|
|
||||||
"jmespath": "0.15.0",
|
|
||||||
"querystring": "0.2.0",
|
|
||||||
"sax": "1.2.1",
|
|
||||||
"url": "0.10.3",
|
|
||||||
"uuid": "3.3.2",
|
|
||||||
"xml2js": "0.4.19"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/axios": {
|
|
||||||
"version": "0.24.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
|
|
||||||
"integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
|
|
||||||
"dependencies": {
|
|
||||||
"follow-redirects": "^1.14.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/base64-js": {
|
|
||||||
"version": "1.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
|
||||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/feross"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "patreon",
|
|
||||||
"url": "https://www.patreon.com/feross"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "consulting",
|
|
||||||
"url": "https://feross.org/support"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/buffer": {
|
|
||||||
"version": "4.9.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
|
|
||||||
"integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
|
|
||||||
"dependencies": {
|
|
||||||
"base64-js": "^1.0.2",
|
|
||||||
"ieee754": "^1.1.4",
|
|
||||||
"isarray": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/cliui": {
|
|
||||||
"version": "7.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
|
|
||||||
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"string-width": "^4.2.0",
|
|
||||||
"strip-ansi": "^6.0.0",
|
|
||||||
"wrap-ansi": "^7.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/color-convert": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"color-name": "~1.1.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=7.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/color-name": {
|
|
||||||
"version": "1.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
|
||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
|
||||||
},
|
|
||||||
"node_modules/emoji-regex": {
|
|
||||||
"version": "8.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
|
||||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
|
||||||
},
|
|
||||||
"node_modules/escalade": {
|
|
||||||
"version": "3.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
|
||||||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/events": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
|
|
||||||
"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.4.x"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/follow-redirects": {
|
|
||||||
"version": "1.14.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz",
|
|
||||||
"integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==",
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "individual",
|
|
||||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"debug": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/fs-extra": {
|
|
||||||
"version": "10.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
|
|
||||||
"integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"graceful-fs": "^4.2.0",
|
|
||||||
"jsonfile": "^6.0.1",
|
|
||||||
"universalify": "^2.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/get-caller-file": {
|
|
||||||
"version": "2.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
|
||||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
|
||||||
"engines": {
|
|
||||||
"node": "6.* || 8.* || >= 10.*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/graceful-fs": {
|
|
||||||
"version": "4.2.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
|
|
||||||
"integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg=="
|
|
||||||
},
|
|
||||||
"node_modules/ieee754": {
|
|
||||||
"version": "1.1.13",
|
|
||||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
|
|
||||||
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
|
|
||||||
},
|
|
||||||
"node_modules/is-fullwidth-code-point": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/isarray": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
|
||||||
},
|
|
||||||
"node_modules/jmespath": {
|
|
||||||
"version": "0.15.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz",
|
|
||||||
"integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.6.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/jsonfile": {
|
|
||||||
"version": "6.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
|
||||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"universalify": "^2.0.0"
|
|
||||||
},
|
|
||||||
"optionalDependencies": {
|
|
||||||
"graceful-fs": "^4.1.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/punycode": {
|
|
||||||
"version": "1.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
|
|
||||||
"integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
|
|
||||||
},
|
|
||||||
"node_modules/querystring": {
|
|
||||||
"version": "0.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
|
||||||
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
|
|
||||||
"deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.4.x"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/require-directory": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
|
||||||
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/sax": {
|
|
||||||
"version": "1.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
|
|
||||||
"integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o="
|
|
||||||
},
|
|
||||||
"node_modules/string-width": {
|
|
||||||
"version": "4.2.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
|
||||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
|
||||||
"dependencies": {
|
|
||||||
"emoji-regex": "^8.0.0",
|
|
||||||
"is-fullwidth-code-point": "^3.0.0",
|
|
||||||
"strip-ansi": "^6.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/strip-ansi": {
|
|
||||||
"version": "6.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
|
||||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-regex": "^5.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/universalify": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/url": {
|
|
||||||
"version": "0.10.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz",
|
|
||||||
"integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=",
|
|
||||||
"dependencies": {
|
|
||||||
"punycode": "1.3.2",
|
|
||||||
"querystring": "0.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"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/wrap-ansi": {
|
|
||||||
"version": "7.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
|
||||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-styles": "^4.0.0",
|
|
||||||
"string-width": "^4.1.0",
|
|
||||||
"strip-ansi": "^6.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/xml2js": {
|
|
||||||
"version": "0.4.19",
|
|
||||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
|
|
||||||
"integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
|
|
||||||
"dependencies": {
|
|
||||||
"sax": ">=0.6.0",
|
|
||||||
"xmlbuilder": "~9.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/xmlbuilder": {
|
|
||||||
"version": "9.0.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
|
|
||||||
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/y18n": {
|
|
||||||
"version": "5.0.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
|
||||||
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/yargs": {
|
|
||||||
"version": "17.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.0.tgz",
|
|
||||||
"integrity": "sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew==",
|
|
||||||
"dependencies": {
|
|
||||||
"cliui": "^7.0.2",
|
|
||||||
"escalade": "^3.1.1",
|
|
||||||
"get-caller-file": "^2.0.5",
|
|
||||||
"require-directory": "^2.1.1",
|
|
||||||
"string-width": "^4.2.3",
|
|
||||||
"y18n": "^5.0.5",
|
|
||||||
"yargs-parser": "^21.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/yargs-parser": {
|
|
||||||
"version": "21.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz",
|
|
||||||
"integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-regex": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
|
|
||||||
},
|
|
||||||
"ansi-styles": {
|
|
||||||
"version": "4.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
|
||||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
|
||||||
"requires": {
|
|
||||||
"color-convert": "^2.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"aws-sdk": {
|
|
||||||
"version": "2.1027.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1027.0.tgz",
|
|
||||||
"integrity": "sha512-j3UjPV9hzyCvkmfcbhRscMggdmrPqlhvo8QzkXCGFfPXjZMh1OJd4HkCEH2NaunzLOyF2Y3QzxKrGOLMT7sNzg==",
|
|
||||||
"requires": {
|
|
||||||
"buffer": "4.9.2",
|
|
||||||
"events": "1.1.1",
|
|
||||||
"ieee754": "1.1.13",
|
|
||||||
"jmespath": "0.15.0",
|
|
||||||
"querystring": "0.2.0",
|
|
||||||
"sax": "1.2.1",
|
|
||||||
"url": "0.10.3",
|
|
||||||
"uuid": "3.3.2",
|
|
||||||
"xml2js": "0.4.19"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"axios": {
|
|
||||||
"version": "0.24.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
|
|
||||||
"integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
|
|
||||||
"requires": {
|
|
||||||
"follow-redirects": "^1.14.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"base64-js": {
|
|
||||||
"version": "1.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
|
||||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
|
|
||||||
},
|
|
||||||
"buffer": {
|
|
||||||
"version": "4.9.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
|
|
||||||
"integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
|
|
||||||
"requires": {
|
|
||||||
"base64-js": "^1.0.2",
|
|
||||||
"ieee754": "^1.1.4",
|
|
||||||
"isarray": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"cliui": {
|
|
||||||
"version": "7.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
|
|
||||||
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
|
|
||||||
"requires": {
|
|
||||||
"string-width": "^4.2.0",
|
|
||||||
"strip-ansi": "^6.0.0",
|
|
||||||
"wrap-ansi": "^7.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"color-convert": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
|
||||||
"requires": {
|
|
||||||
"color-name": "~1.1.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"color-name": {
|
|
||||||
"version": "1.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
|
||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
|
||||||
},
|
|
||||||
"emoji-regex": {
|
|
||||||
"version": "8.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
|
||||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
|
||||||
},
|
|
||||||
"escalade": {
|
|
||||||
"version": "3.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
|
||||||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
|
|
||||||
},
|
|
||||||
"events": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
|
|
||||||
"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
|
|
||||||
},
|
|
||||||
"follow-redirects": {
|
|
||||||
"version": "1.14.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz",
|
|
||||||
"integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA=="
|
|
||||||
},
|
|
||||||
"fs-extra": {
|
|
||||||
"version": "10.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
|
|
||||||
"integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
|
|
||||||
"requires": {
|
|
||||||
"graceful-fs": "^4.2.0",
|
|
||||||
"jsonfile": "^6.0.1",
|
|
||||||
"universalify": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"get-caller-file": {
|
|
||||||
"version": "2.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
|
||||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
|
|
||||||
},
|
|
||||||
"graceful-fs": {
|
|
||||||
"version": "4.2.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
|
|
||||||
"integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg=="
|
|
||||||
},
|
|
||||||
"ieee754": {
|
|
||||||
"version": "1.1.13",
|
|
||||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
|
|
||||||
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
|
|
||||||
},
|
|
||||||
"is-fullwidth-code-point": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
|
||||||
},
|
|
||||||
"isarray": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
|
||||||
},
|
|
||||||
"jmespath": {
|
|
||||||
"version": "0.15.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz",
|
|
||||||
"integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc="
|
|
||||||
},
|
|
||||||
"jsonfile": {
|
|
||||||
"version": "6.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
|
||||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
|
||||||
"requires": {
|
|
||||||
"graceful-fs": "^4.1.6",
|
|
||||||
"universalify": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"punycode": {
|
|
||||||
"version": "1.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
|
|
||||||
"integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
|
|
||||||
},
|
|
||||||
"querystring": {
|
|
||||||
"version": "0.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
|
||||||
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
|
|
||||||
},
|
|
||||||
"require-directory": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
|
||||||
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
|
|
||||||
},
|
|
||||||
"sax": {
|
|
||||||
"version": "1.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
|
|
||||||
"integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o="
|
|
||||||
},
|
|
||||||
"string-width": {
|
|
||||||
"version": "4.2.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
|
||||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
|
||||||
"requires": {
|
|
||||||
"emoji-regex": "^8.0.0",
|
|
||||||
"is-fullwidth-code-point": "^3.0.0",
|
|
||||||
"strip-ansi": "^6.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"strip-ansi": {
|
|
||||||
"version": "6.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
|
||||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
|
||||||
"requires": {
|
|
||||||
"ansi-regex": "^5.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"universalify": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ=="
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"version": "0.10.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz",
|
|
||||||
"integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=",
|
|
||||||
"requires": {
|
|
||||||
"punycode": "1.3.2",
|
|
||||||
"querystring": "0.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"uuid": {
|
|
||||||
"version": "3.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
|
|
||||||
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
|
|
||||||
},
|
|
||||||
"wrap-ansi": {
|
|
||||||
"version": "7.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
|
||||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
|
||||||
"requires": {
|
|
||||||
"ansi-styles": "^4.0.0",
|
|
||||||
"string-width": "^4.1.0",
|
|
||||||
"strip-ansi": "^6.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"xml2js": {
|
|
||||||
"version": "0.4.19",
|
|
||||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
|
|
||||||
"integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
|
|
||||||
"requires": {
|
|
||||||
"sax": ">=0.6.0",
|
|
||||||
"xmlbuilder": "~9.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"xmlbuilder": {
|
|
||||||
"version": "9.0.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
|
|
||||||
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
|
|
||||||
},
|
|
||||||
"y18n": {
|
|
||||||
"version": "5.0.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
|
||||||
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
|
|
||||||
},
|
|
||||||
"yargs": {
|
|
||||||
"version": "17.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.0.tgz",
|
|
||||||
"integrity": "sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew==",
|
|
||||||
"requires": {
|
|
||||||
"cliui": "^7.0.2",
|
|
||||||
"escalade": "^3.1.1",
|
|
||||||
"get-caller-file": "^2.0.5",
|
|
||||||
"require-directory": "^2.1.1",
|
|
||||||
"string-width": "^4.2.3",
|
|
||||||
"y18n": "^5.0.5",
|
|
||||||
"yargs-parser": "^21.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"yargs-parser": {
|
|
||||||
"version": "21.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz",
|
|
||||||
"integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"dependencies": {
|
|
||||||
"aws-sdk": "^2.1026.0",
|
|
||||||
"axios": "^0.24.0",
|
|
||||||
"fs-extra": "^10.0.0",
|
|
||||||
"yargs": "^17.3.0"
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,110 +0,0 @@
|
||||||
const { Axios } = require('axios');
|
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
|
|
||||||
const { API_KEY } = require('../batch-config.json');
|
|
||||||
|
|
||||||
const getDataDictionaryOptions = (providerUoi, recipientUoi, data) => {
|
|
||||||
if (!providerUoi) throw new Error('providerUoi is required!');
|
|
||||||
if (!recipientUoi) throw new Error('recipientUoi is required!');
|
|
||||||
if (!data) throw new Error('data is required!');
|
|
||||||
|
|
||||||
return {
|
|
||||||
'method': "post",
|
|
||||||
'baseURL': 'https://certification.reso.org',
|
|
||||||
'url': `/api/v1/certification_reports/data_dictionary/${providerUoi}`,
|
|
||||||
'headers': {
|
|
||||||
'Authorization': `ApiKey ${API_KEY}`,
|
|
||||||
'recipientUoi': recipientUoi,
|
|
||||||
'Content-Type': "application/json",
|
|
||||||
'User-Agent': "CommanderBatchProcess/0.1",
|
|
||||||
'Accept': "*/*",
|
|
||||||
'Cache-Control': "no-cache",
|
|
||||||
'Host': 'certification.reso.org',
|
|
||||||
'Accept-Encoding': 'gzip, deflate',
|
|
||||||
'Connection': 'keep-alive'
|
|
||||||
},
|
|
||||||
data
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const getDataAvailabilityOptions = (metadataReportId, data) => {
|
|
||||||
if (!metadataReportId) throw new Error('metadataReportId is required!');
|
|
||||||
if (!data) throw new Error('data is required!');
|
|
||||||
|
|
||||||
return {
|
|
||||||
'method': "post",
|
|
||||||
'baseURL': 'https://certification.reso.org',
|
|
||||||
'url': `/api/v1/payload/data_availability/${metadataReportId}`,
|
|
||||||
'headers': {
|
|
||||||
'Authorization': `ApiKey ${API_KEY}`,
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'User-Agent': 'CommanderBatchProcess/0.1',
|
|
||||||
'Accept': '*/*',
|
|
||||||
'Cache-Control': 'no-cache',
|
|
||||||
'Host': 'certification.reso.org',
|
|
||||||
'Accept-Encoding': 'gzip, deflate',
|
|
||||||
'Connection': 'keep-alive'
|
|
||||||
},
|
|
||||||
data
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const buildDataDictionaryResultsPath = (providerUoi, recipientUoi) => `${providerUoi}/${recipientUoi}/metadata-report.json`;
|
|
||||||
const buildDataAvailabilityResultsPath = (providerUoi, recipientUoi) => `${providerUoi}/${recipientUoi}/data-availability-report.json`;
|
|
||||||
|
|
||||||
const postDataDictionaryResultsToApi = async (providerUoi, recipientUoi) => {
|
|
||||||
if (!providerUoi) throw new Error('providerUoi is required!');
|
|
||||||
if (!recipientUoi) throw new Error('recipientUoi is required!');
|
|
||||||
|
|
||||||
try {
|
|
||||||
const data = await fs.readFileAsync(buildDataDictionaryResultsPath(providerUoi, recipientUoi), 'utf8');
|
|
||||||
|
|
||||||
const response = await Axios.post(getDataDictionaryOptions(providerUoi, recipientUoi, data));
|
|
||||||
|
|
||||||
if (!response.id) throw new Error('Did not receive the required id parameter from the response!');
|
|
||||||
|
|
||||||
return response.id;
|
|
||||||
} catch (err) {
|
|
||||||
throw new Error('Could not post data dictionary results to API!' + '\n' + err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const postDataAvailabilityResultsToApi = async (metadataReportId, providerUoi, recipientUoi) => {
|
|
||||||
try {
|
|
||||||
const data = await fs.readFileAsync(buildDataAvailabilityResultsPath(providerUoi, recipientUoi), 'utf8');
|
|
||||||
|
|
||||||
const response = await Axios.post(getDataAvailabilityOptions(metadataReportId, data));
|
|
||||||
|
|
||||||
if (!response || !response.success) throw new Error('Api did not report a successful response! ');
|
|
||||||
|
|
||||||
return response.id;
|
|
||||||
} catch (err) {
|
|
||||||
throw new Error('Could not post data availability results to API!' + '\n' + err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const snooze = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
||||||
|
|
||||||
const processDataDictionaryResults = async (providerUoi, recipientUoi) => {
|
|
||||||
try {
|
|
||||||
await snooze(5 * 1000); //wait 5s for the dust to settle to avoid thrashing the server
|
|
||||||
console.log('Posting Data Dictionary results...');
|
|
||||||
const reportId = await postDataDictionaryResultsToApi(providerUoi, recipientUoi);
|
|
||||||
console.log('Results posted, reportId: ' + reportId);
|
|
||||||
|
|
||||||
await snooze(5 * 1000); //wait 5s for the dust to settle to avoid thrashing the server
|
|
||||||
|
|
||||||
if (reportId) {
|
|
||||||
console.log('Posting data availability results for reportId')
|
|
||||||
return await postDataAvailabilityResultsToApi(reportId, providerUoi, recipientUoi);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
throw new Error('Could not process data dictionary results! \nError:' + err);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
processDataDictionaryResults
|
|
||||||
}
|
|
|
@ -1,324 +0,0 @@
|
||||||
const fs = require('fs').promises;
|
|
||||||
const { standardMeta } = require('../references/standardMeta');
|
|
||||||
const { lookupMap } = require('../references/lookupMap.js');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines the bins template for stats.
|
|
||||||
* @returns bins template with all bins initialized to 0.
|
|
||||||
*/
|
|
||||||
const getBinsTemplate = () => {
|
|
||||||
return {
|
|
||||||
eq0: 0,
|
|
||||||
gt0: 0,
|
|
||||||
gte25: 0,
|
|
||||||
gte50: 0,
|
|
||||||
gte75: 0,
|
|
||||||
eq100: 0
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines the totals template for stats.
|
|
||||||
* @returns totals template with all bins initialized to 0.
|
|
||||||
*/
|
|
||||||
const getTotalsTemplate = () => {
|
|
||||||
return {
|
|
||||||
total: getBinsTemplate(),
|
|
||||||
reso: getBinsTemplate(),
|
|
||||||
idx: getBinsTemplate(),
|
|
||||||
local: getBinsTemplate()
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines the availability template for stats. This is the structure of the processed results.
|
|
||||||
* @returns availability template with all totals and bins initialized to 0.
|
|
||||||
*/
|
|
||||||
const getAvailabilityTemplate = () => {
|
|
||||||
return {
|
|
||||||
fields: [],
|
|
||||||
lookups: [],
|
|
||||||
lookupValues: [],
|
|
||||||
resources: [],
|
|
||||||
availability: {
|
|
||||||
fields: getTotalsTemplate(),
|
|
||||||
lookups: getTotalsTemplate(),
|
|
||||||
resources: {},
|
|
||||||
resourcesBinary: {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a standard field cache from a list of standard fields.
|
|
||||||
* @param {Array} fields an array of standard fields.
|
|
||||||
* @returns map of all standard fields addressable by cache[resourceName][fieldName]
|
|
||||||
* or an empty map if there are none.
|
|
||||||
*/
|
|
||||||
const createStandardFieldCache = (fields = []) => {
|
|
||||||
const resourceFieldCache = {};
|
|
||||||
fields.forEach(field => {
|
|
||||||
if (!resourceFieldCache[field.resourceName]) {
|
|
||||||
resourceFieldCache[field.resourceName] = {};
|
|
||||||
}
|
|
||||||
resourceFieldCache[field.resourceName][field.fieldName] = field;
|
|
||||||
});
|
|
||||||
return resourceFieldCache;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a lookup value cache from a list of individual lookup value items.
|
|
||||||
* @param {Array} lookupValues the lookup values to create the cache from.
|
|
||||||
* @returns map of all lookups addressable by cache[resourceName][fieldName][lookupValue]
|
|
||||||
* or an empty map if there are none.
|
|
||||||
*/
|
|
||||||
const createLookupValueCache = (lookupValues = []) => {
|
|
||||||
const resourceFieldLookupCache = {};
|
|
||||||
lookupValues.forEach(lookupValue => {
|
|
||||||
if (!resourceFieldLookupCache[lookupValue.resourceName]) {
|
|
||||||
resourceFieldLookupCache[lookupValue.resourceName] = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!resourceFieldLookupCache[lookupValue.resourceName][lookupValue.fieldName]) {
|
|
||||||
resourceFieldLookupCache[lookupValue.resourceName][lookupValue.fieldName] = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
resourceFieldLookupCache[lookupValue.resourceName][lookupValue.fieldName][lookupValue.lookupValue] = lookupValue;
|
|
||||||
});
|
|
||||||
return resourceFieldLookupCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether a given field is an IDX field.
|
|
||||||
* TODO: The performance could be improved here in that there's a filter being done on each payloads array.
|
|
||||||
* There's potential speedup if each payload were turned into a nested property rather than an array.
|
|
||||||
* @param {String} resourceName the name of the resource for the field.
|
|
||||||
* @param {String} fieldName the name of the field.
|
|
||||||
* @param {Object} standardFieldCache a field cache created by createStandardFieldCache().
|
|
||||||
* @returns true if the given field is an IDX field, false otherwise.
|
|
||||||
*/
|
|
||||||
const isIdxField = (resourceName, fieldName, standardFieldCache = {}) => resourceName && fieldName
|
|
||||||
&& isResoField(resourceName, fieldName, standardFieldCache)
|
|
||||||
&& !!standardFieldCache[resourceName][fieldName].payloads.filter(x => x === "IDX").length > 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether a given field is a RESO field.
|
|
||||||
* @param {String} resourceName the name of the resource for the field.
|
|
||||||
* @param {String} fieldName the name of the field.
|
|
||||||
* @param {Object} standardFieldCache a field cache created by createStandardFieldCache().
|
|
||||||
* @returns true if the given field is a RESO field, false otherwise.
|
|
||||||
*/
|
|
||||||
const isResoField = (resourceName, fieldName, standardFieldCache = {}) => resourceName && fieldName
|
|
||||||
&& standardFieldCache[resourceName] && !!standardFieldCache[resourceName][fieldName];
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if a given lookup is a RESO lookup.
|
|
||||||
* @param {*} resourceName the name of the resource for the field.
|
|
||||||
* @param {*} fieldName the name of the field.
|
|
||||||
* @param {*} lookupValue the name of the lookup to test.
|
|
||||||
* @param {*} standardFieldCache a field cache created by createStandardFieldCache().
|
|
||||||
* @returns the RESO lookup, if found, otherwise null.
|
|
||||||
*/
|
|
||||||
const findResoLookup = (resourceName, fieldName, lookupValue, standardFieldCache = {}) => {
|
|
||||||
if (resourceName && fieldName && standardFieldCache[resourceName] && standardFieldCache[resourceName][fieldName]) {
|
|
||||||
const field = standardFieldCache[resourceName][fieldName];
|
|
||||||
|
|
||||||
if (field && field.simpleDataType.includes('String List') && field.type.includes('.')) {
|
|
||||||
const lookupName = field.type.substring(field.type.lastIndexOf('.') + 1, field.type.length);
|
|
||||||
const lookup = lookupMap[lookupName] && lookupMap[lookupName].find(x => x.lookupValue === lookupValue || x.lookupDisplayName === lookupValue);
|
|
||||||
//TODO: turn the lookup map into its own inverted hash by lookup values and display names
|
|
||||||
return lookup ? { lookupName, lookup } : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes availability from existing bins.
|
|
||||||
* @param {Number} availability the current availability value.
|
|
||||||
* @param {Object} bins existing bins containing past availability values.
|
|
||||||
* @returns a new object following the getBinsTemplate structure that contains updated availabilities for each bin.
|
|
||||||
*/
|
|
||||||
const computeBins = (availability, bins) => {
|
|
||||||
if (!bins) return getBinsTemplate();
|
|
||||||
return {
|
|
||||||
eq0: availability === 0 ? bins.eq0 + 1 : bins.eq0 || 0,
|
|
||||||
gt0: availability > 0 ? bins.gt0 + 1 : bins.gt0 || 0,
|
|
||||||
gte25: availability >= 0.25 ? bins.gte25 + 1 : bins.gte25 || 0,
|
|
||||||
gte50: availability >= 0.5 ? bins.gte50 + 1 : bins.gte50 || 0,
|
|
||||||
gte75: availability >= 0.75 ? bins.gte75 + 1 : bins.gte75 || 0,
|
|
||||||
eq100: availability === 1 ? bins.eq100 + 1 : bins.eq100 || 0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates existing numeric bins into booleans.
|
|
||||||
* @param {Object} bins existing bins object.
|
|
||||||
* @returns the resulting bins object with values transformed to booleans.
|
|
||||||
*/
|
|
||||||
const computeBooleanBins = bins => {
|
|
||||||
const booleanBins = {};
|
|
||||||
Object.entries(bins).forEach( ([bin, value]) => booleanBins[bin] = !!value);
|
|
||||||
return booleanBins;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes availability from discrete bins, meaning ones with integer values (tallies).
|
|
||||||
* @param {Object} discreteBins bins using the getBinsTemplate() structure with integer availability values.
|
|
||||||
* @param {Number} resourceSampleCount the count of the number of sampled records for a given resource.
|
|
||||||
* @returns a bins object with the decimal availabilities computed.
|
|
||||||
*/
|
|
||||||
const computeAvailabilityFromDiscreteBins = (discreteBins=getBinsTemplate(), resourceSampleCount=0) => {
|
|
||||||
if (!resourceSampleCount) return discreteBins;
|
|
||||||
|
|
||||||
const availabilities = {};
|
|
||||||
Object.entries(discreteBins).forEach(([binName, value]) => availabilities[binName] = 1.0 * value / resourceSampleCount);
|
|
||||||
return availabilities;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes a RESO Data Availability Report and creates aggregates and rollups.
|
|
||||||
* TODO: individual totals calculations could be tidied up a bit.
|
|
||||||
* @param {Object} availablityReport the RESO availability report JSON to process.
|
|
||||||
* @returns a JSON availability report with the appropriate rollups and aggregates.
|
|
||||||
*/
|
|
||||||
const process = async availablityReport => {
|
|
||||||
//iterate over each field and lookup and compute their availabilities
|
|
||||||
const { resources, fields, lookups, lookupValues } = availablityReport;
|
|
||||||
|
|
||||||
const transformed = getAvailabilityTemplate();
|
|
||||||
const standardFieldCache = createStandardFieldCache(standardMeta.fields);
|
|
||||||
|
|
||||||
const resourceCounts = {};
|
|
||||||
resources.forEach(resource => resourceCounts[resource.resourceName] = resource.numRecordsFetched);
|
|
||||||
|
|
||||||
const processedFields = [], processedLookupValues = [], lookupValueCache = createLookupValueCache(lookupValues);
|
|
||||||
|
|
||||||
//binary resource availability cache
|
|
||||||
const resourcesBinary = {};
|
|
||||||
|
|
||||||
//process fields
|
|
||||||
fields.forEach(field => {
|
|
||||||
const availability = resourceCounts[field.resourceName] !== 0 ? 1.0 * field.frequency / resourceCounts[field.resourceName] : 0;
|
|
||||||
const fieldBins = computeBins(availability, getBinsTemplate());
|
|
||||||
|
|
||||||
//update field availability
|
|
||||||
transformed.availability.fields.total = computeBins(availability, transformed.availability.fields.total);
|
|
||||||
|
|
||||||
//add totals template for this resource name if it doesn't already exist
|
|
||||||
if (!resourcesBinary[field.resourceName]) {
|
|
||||||
resourcesBinary[field.resourceName] = { fields: getTotalsTemplate(), lookups: getTotalsTemplate() };
|
|
||||||
}
|
|
||||||
//update binary resource bins
|
|
||||||
resourcesBinary[field.resourceName].fields.total = computeBins(availability, resourcesBinary[field.resourceName].fields.total);
|
|
||||||
|
|
||||||
if (isResoField(field.resourceName, field.fieldName, standardFieldCache)) {
|
|
||||||
//update RESO totals
|
|
||||||
transformed.availability.fields.reso = computeBins(availability, transformed.availability.fields.reso);
|
|
||||||
resourcesBinary[field.resourceName].fields.reso = computeBins(availability, resourcesBinary[field.resourceName].fields.reso);
|
|
||||||
|
|
||||||
if (isIdxField(field.resourceName, field.fieldName, standardFieldCache)) {
|
|
||||||
//update IDX totals
|
|
||||||
transformed.availability.fields.idx = computeBins(availability, transformed.availability.fields.idx);
|
|
||||||
resourcesBinary[field.resourceName].fields.idx = computeBins(availability, resourcesBinary[field.resourceName].fields.idx);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//otherwise, update local totals
|
|
||||||
transformed.availability.fields.local = computeBins(availability, transformed.availability.fields.local);
|
|
||||||
resourcesBinary[field.resourceName].fields.local = computeBins(availability, resourcesBinary[field.resourceName].fields.local);
|
|
||||||
}
|
|
||||||
|
|
||||||
//only process if there are lookups for this field
|
|
||||||
const lookupsForField = lookupValueCache[field.resourceName] && lookupValueCache[field.resourceName][field.fieldName];
|
|
||||||
|
|
||||||
if (lookupsForField) {
|
|
||||||
Object.values(lookupsForField).forEach(lookupValue => {
|
|
||||||
if (lookupValue.lookupValue !== 'null' && lookupValue.lookupValue !== 'NULL_VALUE') {
|
|
||||||
const lookupAvailability = !!lookupValue.frequency && !!resourceCounts[field.resourceName]
|
|
||||||
? 1.0 * lookupValue.frequency / resourceCounts[field.resourceName] : 0;
|
|
||||||
|
|
||||||
const lookupBins = computeBins(lookupAvailability, getBinsTemplate());
|
|
||||||
|
|
||||||
transformed.availability.lookups.total = computeBins(availability, transformed.availability.lookups.total);
|
|
||||||
resourcesBinary[field.resourceName].lookups.total = computeBins(availability, resourcesBinary[field.resourceName].lookups.total);
|
|
||||||
|
|
||||||
if (isResoField(lookupValue.resourceName, lookupValue.fieldName, standardFieldCache) &&
|
|
||||||
findResoLookup(lookupValue.resourceName, lookupValue.fieldName, lookupValue.lookupValue, standardFieldCache)) {
|
|
||||||
|
|
||||||
transformed.availability.lookups.reso = computeBins(availability, transformed.availability.lookups.reso);
|
|
||||||
resourcesBinary[field.resourceName].lookups.reso = computeBins(availability, resourcesBinary[field.resourceName].lookups.reso);
|
|
||||||
if (isIdxField(lookupValue.resourceName, lookupValue.fieldName, standardFieldCache)) {
|
|
||||||
transformed.availability.lookups.idx = computeBins(availability, transformed.availability.lookups.idx);
|
|
||||||
resourcesBinary[field.resourceName].lookups.idx = computeBins(availability, resourcesBinary[field.resourceName].lookups.idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
transformed.availability.lookups.local = computeBins(availability, transformed.availability.lookups.local);
|
|
||||||
resourcesBinary[field.resourceName].lookups.local = computeBins(availability, resourcesBinary[field.resourceName].lookups.local);
|
|
||||||
}
|
|
||||||
|
|
||||||
processedLookupValues.push({ ...lookupValue, lookupAvailability, ...computeBooleanBins(lookupBins) });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!!field) {
|
|
||||||
processedFields.push({ ...field, availability, ...computeBooleanBins(fieldBins) });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
transformed.resources = resources;
|
|
||||||
transformed.fields = processedFields;
|
|
||||||
transformed.lookups = lookups;
|
|
||||||
transformed.lookupValues = processedLookupValues;
|
|
||||||
transformed.availability.resourcesBinary = resourcesBinary;
|
|
||||||
|
|
||||||
//compute resource availability rollups from the discrete bins
|
|
||||||
const resourceAvailability = {};
|
|
||||||
transformed.availability.resources = Object.entries(resourcesBinary).forEach(([resourceName, value]) => {
|
|
||||||
if (!resourceAvailability[resourceName]) resourceAvailability[resourceName] = {};
|
|
||||||
|
|
||||||
const { fields = getTotalsTemplate(), lookups = getTotalsTemplate() } = value;
|
|
||||||
const resourceCount = resourceCounts[resourceName] || 0;
|
|
||||||
|
|
||||||
resourceAvailability[resourceName].fields = {
|
|
||||||
total: computeAvailabilityFromDiscreteBins(fields.total, resourceCount),
|
|
||||||
reso: computeAvailabilityFromDiscreteBins(fields.reso, resourceCount),
|
|
||||||
idx: computeAvailabilityFromDiscreteBins(fields.idx, resourceCount),
|
|
||||||
local: computeAvailabilityFromDiscreteBins(fields.local, resourceCount)
|
|
||||||
};
|
|
||||||
|
|
||||||
resourceAvailability[resourceName].lookups = {
|
|
||||||
total: computeAvailabilityFromDiscreteBins(lookups.total, resourceCount),
|
|
||||||
reso: computeAvailabilityFromDiscreteBins(lookups.reso, resourceCount),
|
|
||||||
idx: computeAvailabilityFromDiscreteBins(lookups.idx, resourceCount),
|
|
||||||
local: computeAvailabilityFromDiscreteBins(lookups.local, resourceCount)
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
transformed.availability.resources = resourceAvailability;
|
|
||||||
|
|
||||||
return transformed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes a RESO data availability report at the given path and writes it to a local file
|
|
||||||
* in the current path called 'availability-processed.json'.
|
|
||||||
* @param {String} pathToDataAvailabilityReport the path to the data availability report to process.
|
|
||||||
*/
|
|
||||||
const processDataAvailabilityReport = async pathToDataAvailabilityReport => {
|
|
||||||
try {
|
|
||||||
const availablityReport = JSON.parse(await fs.readFile(pathToDataAvailabilityReport, 'utf8'));
|
|
||||||
const startTime = new Date();
|
|
||||||
await fs.writeFile('./availability-processed.json', JSON.stringify(await process(availablityReport)));
|
|
||||||
console.log("Time taken: ", new Date() - startTime, "ms");
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
processDataAvailabilityReport
|
|
||||||
};
|
|
Loading…
Reference in New Issue