From 198880773d8e0ed6a1768c2ccc4d3c92d29c7d87 Mon Sep 17 00:00:00 2001
From: csmig
Date: Tue, 13 Feb 2024 11:18:13 -0500
Subject: [PATCH 01/13] notional idea
---
lib/alarm.js | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
create mode 100644 lib/alarm.js
diff --git a/lib/alarm.js b/lib/alarm.js
new file mode 100644
index 0000000..b1599fe
--- /dev/null
+++ b/lib/alarm.js
@@ -0,0 +1,86 @@
+import { EventEmitter } from "node:events"
+
+/**
+ * Represents the state of each alarm type.
+ * @typedef {Object} Alarms
+ * @property {boolean} apiOffline - the STIG manager API is unreachable.
+ * @property {boolean} authOffline - the OIDC IdP is unreachable.
+ * @property {boolean} noToken - the OIDC IdP did not issue the client a token.
+ * @property {boolean} noGrant - the client has an insufficient grant on the configured Collection.
+ */
+
+/**
+ * @typedef {'apiOffline' | 'authOffline' | 'noToken' | 'noGrant'} AlarmType
+ */
+
+class Alarm extends EventEmitter {
+ /** @type {Alarms} */
+ #alarms
+
+ constructor () {
+ super()
+ this.#alarms = {
+ apiOffline: false,
+ authOffline: false,
+ noToken: false,
+ noGrant: false,
+ }
+ }
+
+ /**
+ * Emits 'alarmRaised' or 'alarmLowered' based on 'state', passing the alarmType
+ * @param {AlarmType} event
+ * @param {boolean} state
+ */
+ #emitAlarmEvent (alarmType, state) {
+ if (state) {
+ this.emit('alarmRaised', alarmType)
+ }
+ else {
+ this.emit('alarmLowered', alarmType)
+ }
+ }
+
+ /**
+ * Sets the state of the apiOffline alarm
+ * @param {boolean} state
+ */
+ apiOffline (state) {
+ this.#alarms.apiOffline = state
+ this.#emitAlarmEvent( 'apiOffline', state)
+ }
+
+ /**
+ * Sets the state of the authOffline alarm
+ * @param {boolean} state
+ */
+ authOffline (state) {
+ this.#alarms.authOffline = state
+ this.#emitAlarmEvent( 'authOffline', state)
+ }
+
+ /**
+ * Sets the state of the noToken alarm
+ * @param {boolean} state
+ */
+ noToken (state) {
+ this.#alarms.noToken = state
+ this.#emitAlarmEvent( 'noToken', state)
+ }
+
+ /**
+ * Sets the state of the noGrant alarm
+ * @param {boolean} state
+ */
+ noGrant (state) {
+ this.#alarms.noGrant = state
+ this.#emitAlarmEvent( 'noGrant', state)
+ }
+
+ /** @type {Alarms} */
+ get alarms() {
+ return this.#alarms
+ }
+}
+
+export default new Alarm()
\ No newline at end of file
From eebe4653844e8348dd1981605233d572a9fcb4f3 Mon Sep 17 00:00:00 2001
From: csmig
Date: Fri, 1 Mar 2024 12:27:01 -0500
Subject: [PATCH 02/13] Squashed commit of the following:
commit f08e1878ef3959341195a655c64866e61c8f3a39
Author: csmig <33138761+csmig@users.noreply.github.com>
Date: Thu Feb 29 18:58:21 2024 +0000
chore: remove/update dependencies (#97)
commit a70d38a4310389781c14ea0e9b4d6759e183320c
Author: csmig <33138761+csmig@users.noreply.github.com>
Date: Thu Feb 22 19:41:45 2024 +0000
feat: in scan mode, migrate addToHistory() calls to the queue handlers (#93)
Co-authored-by: matte22
commit d0077929cdbd8dc3309f458c24e4a79490f3af5f
Author: Mathew <77069472+Matte22@users.noreply.github.com>
Date: Thu Feb 22 13:28:34 2024 -0500
test: Create Workflow for unit testing. (#92)
commit e398da963cb780c6058c910ed143a36f89874a83
Author: Mathew <77069472+Matte22@users.noreply.github.com>
Date: Mon Feb 19 17:57:22 2024 -0500
feat: scan mode history management (#90)
commit 00f497f810e30105be6179389f25f39f91bda0b9
Author: csmig <33138761+csmig@users.noreply.github.com>
Date: Fri Feb 16 15:37:43 2024 +0000
feat: pass filename to parsers as sourceRef (#91)
---
.github/workflows/sonarcloud.yml | 2 +-
.github/workflows/unit-testing.yml | 40 +
.gitignore | 3 +-
dist/.gitignore | 2 +-
index.js | 13 +-
lib/args.js | 21 +-
lib/cargo.js | 10 +-
lib/parse.js | 19 +-
lib/scan.js | 338 ++++--
package-lock.json | 1660 ++++++++++++++++++++++++----
package.json | 14 +-
test/scan/historyfile.test.js | 247 +++++
12 files changed, 2058 insertions(+), 311 deletions(-)
create mode 100644 .github/workflows/unit-testing.yml
create mode 100644 test/scan/historyfile.test.js
diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml
index 71f6c9e..be37743 100644
--- a/.github/workflows/sonarcloud.yml
+++ b/.github/workflows/sonarcloud.yml
@@ -40,7 +40,7 @@ jobs:
-Dsonar.projectName=NUWCDIVNPT_stigman-watcher
-Dsonar.organization=nuwcdivnpt
-Dsonar.inclusions=**/*.js
- -Dsonar.exclusions=**/node_modules/**,
+ -Dsonar.exclusions=**/node_modules/**,**/test/**,**/coverage/**
# This will fail the action if Quality Gate fails (leaving out for now )
diff --git a/.github/workflows/unit-testing.yml b/.github/workflows/unit-testing.yml
new file mode 100644
index 0000000..c2cbb21
--- /dev/null
+++ b/.github/workflows/unit-testing.yml
@@ -0,0 +1,40 @@
+name: Run Unit Tests and Upload Coverage Artifact
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ paths:
+ - "lib/**"
+ - "index.js"
+ - "test/**"
+ pull_request:
+ branches:
+ - main
+ paths:
+ - "lib/**"
+ - "index.js"
+ - "test/**"
+
+jobs:
+ build_test:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ - name: Setup Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: 18
+ - name: Install app dependencies
+ run: npm ci
+ - name: Create .env file
+ run: echo -e "WATCHER_COLLECTION=1\nWATCHER_API_BASE=url\nWATCHER_AUTHORITY=auth\nWATCHER_CLIENT_ID=clientId\nWATCHER_CLIENT_SECRET=secret" > .env
+ - name: Run tests
+ run: npm test
+ - name: Upload coverage to github
+ uses: actions/upload-artifact@v3
+ if: ${{ always() }}
+ with:
+ name: coverage
+ path: coverage
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 2706b84..d64dc17 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,5 @@ watched/
.env
*.log
log.json
-bundle.js
\ No newline at end of file
+bundle.js
+coverage/
\ No newline at end of file
diff --git a/dist/.gitignore b/dist/.gitignore
index cd84c12..7508a5c 100644
--- a/dist/.gitignore
+++ b/dist/.gitignore
@@ -9,4 +9,4 @@
*
# Except this file
-!.gitignore
+!.gitignore
\ No newline at end of file
diff --git a/index.js b/index.js
index 344f430..1596982 100755
--- a/index.js
+++ b/index.js
@@ -10,11 +10,19 @@ import startFsEventWatcher from './lib/events.js'
import { getOpenIDConfiguration, getToken } from './lib/auth.js'
import * as api from './lib/api.js'
import { serializeError } from 'serialize-error'
-import startScanner from './lib/scan.js'
+import { initScanner } from './lib/scan.js'
import semverGte from 'semver/functions/gte.js'
const minApiVersion = '1.2.7'
+process.on('SIGINT', () => {
+ logger.info({
+ component: 'main',
+ message: 'received SIGINT, exiting'
+ })
+ process.exit(0)
+})
+
run()
async function run() {
@@ -22,6 +30,7 @@ async function run() {
logger.info({
component: 'main',
message: 'running',
+ pid: process.pid,
options: getObfuscatedConfig(options)
})
@@ -30,7 +39,7 @@ async function run() {
startFsEventWatcher()
}
else if (options.mode === 'scan') {
- startScanner()
+ initScanner()
}
}
catch (e) {
diff --git a/lib/args.js b/lib/args.js
index c556140..6ea8d27 100644
--- a/lib/args.js
+++ b/lib/args.js
@@ -14,17 +14,17 @@ const component = 'args'
function getVersion() {
try {
- const packageJsonText = readFileSync('./package.json', 'utf8');
- return JSON.parse(packageJsonText).version;
+ const packageJsonText = readFileSync('./package.json', 'utf8')
+ return JSON.parse(packageJsonText).version
}
catch (error) {
- console.error('Error reading package.json:', error);
+ console.error('Error reading package.json:', error)
}
}
let configValid = true
-const version = getVersion();
+const version = getVersion()
// Use .env, if present, to setup the environment
config()
@@ -54,18 +54,18 @@ const getBoolean = (envvar, defaultState = true) => {
}
}
const parseIntegerArg = (value) => {
- const parsedValue = parseInt(value, 10);
+ const parsedValue = parseInt(value, 10)
if (isNaN(parsedValue)) {
- throw new InvalidOptionArgumentError('Not a number.');
+ throw new InvalidOptionArgumentError('Not a number.')
}
- return parsedValue;
+ return parsedValue
}
const parseIntegerEnv = (value) => {
- const parsedValue = parseInt(value, 10);
+ const parsedValue = parseInt(value, 10)
if (isNaN(parsedValue)) {
return undefined
}
- return parsedValue;
+ return parsedValue
}
// Build the Command
@@ -92,7 +92,8 @@ program
.option('--add-existing', 'For `--mode events`, existing files in the path will generate an `add` event (`WATCHER_ADD_EXISTING=1`). Ignored if `--mode scan`, negate with `--no-add-existing`.', getBoolean('WATCHER_ADD_EXISTING', false))
.option('--no-add-existing', 'Ignore existing files in the watched path (`WATCHER_ADD_EXISTING=0`).')
.option('--cargo-delay ', 'Milliseconds to delay processing the queue (`WATCHER_CARGO_DELAY`)', parseIntegerArg, parseIntegerEnv(pe.WATCHER_CARGO_DELAY) ?? 2000)
-.option('--cargo-size ', 'Maximum queue size that triggers processing (`WATCHER_CARGO_SIZE`)', parseIntegerArg, parseIntegerEnv(pe.WATCHER_CARGO_SIZE) ?? 25)
+.option('--history-write-interval ', 'Interval in milliseconds for when to periodically sync history file(`WATCHER_HISTORY_WRITE_INTERVAL`)', parseIntegerArg, parseIntegerEnv(pe.WATCHER_HISTORY_WRITE_INTERVAL) ?? 15000)
+.option('--cargo-size ', 'Maximum queue size that triggers processing (`WATCHER_CARGO_SIZE`)', parseIntegerArg, parseIntegerEnv(pe.WATCHER_CARGO_SIZE) ?? 10)
.option('--create-objects', 'Create Assets or STIG Assignments as needed (`WATCHER_CREATE_OBJECTS=1`). Negate with `--no-create-objects`.', getBoolean('WATCHER_CREATE_OBJECTS', true))
.option('--no-create-objects', 'Do not create Assets or STIG Assignments (`WATCHER_CREATE_OBJECTS=0`).')
.option('--ignore-dir [name...]', 'DEPRECATED, use --ignore-glob. Sub-directory name to ignore. Can be invoked multiple times.(`WATCHER_IGNORE_DIRS=`)', pe.WATCHER_IGNORE_DIRS?.split(','))
diff --git a/lib/cargo.js b/lib/cargo.js
index ef46260..ffa5814 100644
--- a/lib/cargo.js
+++ b/lib/cargo.js
@@ -3,7 +3,8 @@ import { logger, getSymbol } from './logger.js'
import Queue from 'better-queue'
import * as api from './api.js'
import { serializeError } from 'serialize-error'
-import { TaskObject } from 'stig-manager-client-modules'
+import { TaskObject } from '@nuwcdivnpt/stig-manager-client-modules'
+import { addToHistory } from './scan.js'
const component = 'cargo'
let batchId = 0
@@ -64,6 +65,7 @@ async function writer ( taskAsset ) {
})
}
+ return true
}
catch (error) {
const errorObj = {
@@ -87,6 +89,7 @@ async function writer ( taskAsset ) {
errorObj.error = serializeError(error)
}
logger.error(errorObj)
+ return false
}
}
@@ -94,12 +97,15 @@ async function resultsHandler( parsedResults, cb ) {
const component = 'batch'
try {
batchId++
+ const isModeScan = options.mode === 'scan'
logger.info({component: component, message: `batch started`, batchId: batchId, size: parsedResults.length})
const apiAssets = await api.getCollectionAssets(options.collectionId)
const apiStigs = await api.getInstalledStigs()
const tasks = new TaskObject ({ parsedResults, apiAssets, apiStigs, options:options })
+ isModeScan && tasks.errors.length && addToHistory(tasks.errors.map(e => e.sourceRef))
for ( const taskAsset of tasks.taskAssets.values() ) {
- await writer( taskAsset )
+ const success = await writer( taskAsset )
+ isModeScan && success && addToHistory(taskAsset.sourceRefs)
}
logger.info({component: component, message: 'batch ended', batchId: batchId})
cb()
diff --git a/lib/parse.js b/lib/parse.js
index f598f94..41bfd7b 100644
--- a/lib/parse.js
+++ b/lib/parse.js
@@ -1,15 +1,11 @@
import { cache } from './api.js'
-import { XMLParser } from 'fast-xml-parser'
import Queue from 'better-queue'
import { logger } from './logger.js'
import { cargoQueue } from './cargo.js'
import { promises as fs } from 'fs'
-import he from 'he'
-import { reviewsFromCkl, reviewsFromScc, reviewsFromCklb } from 'stig-manager-client-modules'
-
-const valueProcessor = function (tagName, tagValue, jPath, hasAttributes, isLeafNode) {
- he.decode(tagValue)
-}
+import { reviewsFromCkl, reviewsFromScc, reviewsFromCklb } from '@nuwcdivnpt/stig-manager-client-modules'
+import { addToHistory } from './scan.js'
+import { options } from './args.js'
const defaultImportOptions = {
autoStatus: 'saved',
@@ -69,11 +65,9 @@ async function parseFileAndEnqueue (file, cb) {
importOptions,
fieldSettings,
allowAccept,
- valueProcessor,
- XMLParser,
- scapBenchmarkMap
+ scapBenchmarkMap,
+ sourceRef: file
})
- parseResult.file = file
logger.debug({component: component, message: `parse results`, results: parseResult})
cargoQueue.push( parseResult )
@@ -85,12 +79,13 @@ async function parseFileAndEnqueue (file, cb) {
stats: checklist.stats
})
}
- logger.verbose({component: component, message: `results queued`, file: parseResult.file,
+ logger.verbose({component: component, message: `results queued`, file: parseResult.sourceRef,
target: parseResult.target.name, checklists: checklistInfo })
cb(null, parseResult)
}
catch (e) {
logger.warn({component: component, message: e.message, file: file})
+ options.mode === 'scan' && addToHistory(file)
cb(e, null)
}
}
diff --git a/lib/scan.js b/lib/scan.js
index ced42ca..bde0814 100644
--- a/lib/scan.js
+++ b/lib/scan.js
@@ -1,94 +1,306 @@
-
-import fastGlob from 'fast-glob'
-import {options} from './args.js'
import { logger } from './logger.js'
-import { existsSync, createWriteStream } from 'fs'
-import { queue } from './parse.js'
+import { options } from './args.js'
+import { queue as parseQueue} from './parse.js'
import { serializeError } from 'serialize-error'
+import fg from 'fast-glob'
import lineByLine from 'n-readlines'
-
+import fs from 'node:fs'
const component = 'scan'
-const history = new Set()
-if (options.historyFile && existsSync(options.historyFile)) {
- const liner = new lineByLine(options.historyFile)
- let lineCount = 0
- let line
- while (line = liner.next()) {
- history.add(line.toString('ascii'))
- lineCount++
+const historySet = new Set() // in memory history set
+let isWriteScheduled = false // flag to indicate if there is pending files to write to the history file
+
+/**
+ * Utility function that calls initHistory() and startScanner()
+ */
+function initScanner() {
+ initHistory()
+ startScanner()
+}
+
+/**
+ * Starts a fast-glob stream and manages the history of scanned files.
+ * References options properties {path, ignoreDot, ignoreGlob, oneShot}.
+ */
+async function startScanner() {
+ const discoveredFiles = new Set() // in memory set of files discovered in the current scan
+ try {
+ // scan the path for files
+ const stream = fg.stream([`${options.path}/**/*.ckl`, `${options.path}/**/*.xml`, `${options.path}/**/*.cklb`], {
+ dot: !options.ignoreDot,
+ suppressErrors: true,
+ ignore: options.ignoreGlob ?? []
+ })
+ logger.info({ component, message: `scan started`, path: options.path })
+ // for each file discovered
+ for await (const entry of stream) {
+ discoveredFiles.add(entry)
+ logger.verbose({ component, message: `discovered file`, file: entry })
+ // check if the file is in the history
+ if (historySet.has(entry)) {
+ logger.verbose({component, message: `history match`, file: entry})
+ }
+ // if the file is not in the history, add it to the in memory history set.
+ else {
+ parseQueue.push(entry)
+ logger.info({component, message: `queued for parsing`, file: entry})
+ }
+ }
+ //Remove stale files: those in historySet but not found in the current scan
+ removeStaleFiles(discoveredFiles)
+ logger.info({ component, message: `scan ended`, path: options.path })
+ }
+ catch (e) {
+ logger.error({ component, error: serializeError(e) })
+ }
+ finally {
+ if (!options.oneShot) {
+ scheduleNextScan()
+ }
+ else {
+ logger.info({ component, message: `one-shot scan completed`, path: options.path })
+ }
}
- logger.verbose({
- component: component,
- message: `history initialized from file`,
- file: options.historyFile,
- entries: lineCount
- })
}
-let historyStream
-if (options.historyFile) {
- historyStream = createWriteStream(options.historyFile, { flags: 'a' });
+/**
+ * Deletes entries from historySet that are not present in currentFilesSet.
+ * @param {Set} currentFilesSet - The set of current files.
+ */
+function removeStaleFiles(currentFilesSet){
+ const staleFiles = Array.from(historySet).filter(file => !currentFilesSet.has(file))
+ if (staleFiles.length > 0) {
+ removeFromHistory(staleFiles)
+ }
}
-const interval = options.scanInterval
+/**
+ * Schedules the next scan at options.scanInterval milliseconds from now.
+ * References options properties {path, scanInterval}.
+ */
+function scheduleNextScan() {
+ setTimeout(() => {
+ startScanner().catch(e => {
+ logger.error({ component, error: serializeError(e) })
+ })
+ }, options.scanInterval)
-export default async function startScanner () {
- try {
- const stream = fastGlob.stream([`${options.path}/**/*.ckl`, `${options.path}/**/*.xml`,`${options.path}/**/*.cklb` ], {
- dot: !options.ignoreDot,
- suppressErrors: true,
- ignore: options.ignoreGlob ?? []
+ logger.info({
+ component,
+ message: `scan scheduled`,
+ path: options.path,
+ delay: options.scanInterval
+ })
+}
+
+/**
+ * Returns immediately if options.historyFile is falsy.
+ * Initializes the history Set by reading it from a file and adding each line to the history set.
+ * Creates history file if necessary and if successful sets up SIGINT handler and initializes a write interval.
+ * References options properties {historyFile, historyWriteInterval}
+ */
+function initHistory() {
+ historySet.clear()
+
+ // Log history set values on SIGUSR2
+ process.on('SIGUSR2', logHistory)
+
+ // no history file specified, no need to setup
+ if (!options.historyFile) return
+
+ if (isHistoryFileReadable()) {
+ // initialize history set with content of history file
+ const liner = new lineByLine(options.historyFile)
+ let line
+ while (line = liner.next()) {
+ // add each line to the history set
+ historySet.add(line.toString('ascii'))
+ }
+ logger.verbose({
+ component,
+ message: `history initialized from file`,
+ file:options.historyFile,
})
- logger.info({component: component, message: `scan started`, path: options.path})
+ }
+ else {
+ logger.warn({
+ component,
+ message: 'history file is not readable, scan history is uninitialized',
+ file: options.historyFile
+ })
+ }
- for await (const entry of stream) {
- logger.verbose({component: component, message: `discovered file`, file: entry})
- if (history.has(entry)) {
- logger.verbose({component: component, message: `history match`, file: entry})
- }
- else {
- history.add(entry)
- logger.verbose({component: component, message: `history add`, file: entry})
- if (options.historyFile) _writeHistory(entry)
- queue.push(entry)
- logger.info({component: component, message: `queued for parsing`, file: entry})
- }
+ if (isHistoryFileWriteable()) {
+ // Handle the interrupt signal
+ process.prependListener('SIGINT', interruptHandler)
+ // Set the write interval handler
+ setInterval(writeIntervalHandler, options.historyWriteInterval)
+ logger.verbose({
+ component,
+ message: `history file is writable, periodic writes enabled`,
+ file:options.historyFile,
+ writeInterval: options.historyWriteInterval
+ })
+ }
+ else {
+ logger.warn({
+ component,
+ message: 'history file is not writable, scan history will not be flushed',
+ file: options.historyFile
+ })
+ }
+}
+
+/**
+ * Writes historySet to options.historyFile before exiting.
+ * Intended to be a callback function for the SIGINT signal
+ */
+function interruptHandler() {
+ logger.info({
+ component,
+ message: `received SIGINT, try writing history to file`
+ })
+ writeHistoryToFile()
+}
+
+/**
+ * If isWriteScheduled is true, writes historySet to file and sets isWriteScheduled to false
+ * Intended to be a callback function of setInterval()
+ */
+function writeIntervalHandler() {
+ if (!isWriteScheduled) return
+ writeHistoryToFile()
+ isWriteScheduled = false
+}
+
+/**
+ * Logs an info message with the historySet entries.
+ * Intended to be a callback function for the SIGUSER2 signal
+ */
+function logHistory() {
+ logger.info({
+ component,
+ message: `received SIGUSR2, dumping historySet entries`,
+ history: Array.from(historySet)
+ })
+}
+
+/**
+ * Removes files from the history set and schedules a write to the history file.
+ * @param {string|string[]} files - The file(s) to be removed.
+ */
+function removeFromHistory (files) {
+ // process array of files
+ if (Array.isArray(files)) {
+ for (const entry of files) {
+ historySet.delete(entry)
}
- logger.info({component: component, message: `scan ended`, path: options.path})
}
- catch(e) {
- logger.error({component: component, error: serializeError(e)})
+ // process single file
+ else {
+ historySet.delete(files)
}
- finally {
- if (!options.oneShot) scheduleNextScan()
+
+ isWriteScheduled = true // Indicate that there's work to be done
+ logger.verbose({
+ component,
+ message: `removed from history`,
+ file: files
+ })
+}
+
+/**
+ * Adds files to the history set and schedules a write to the history file.
+ * @param {Array|string} files - The file(s) to be added.
+ */
+function addToHistory (files) {
+ // process array of files
+ if (Array.isArray(files)) {
+ for (const entry of files) {
+ historySet.add(entry)
+ }
+ } else {
+ // single item
+ historySet.add(files)
}
+
+ isWriteScheduled = true
+ logger.verbose({
+ component,
+ message: `added to history`,
+ file: files
+ })
}
-async function _writeHistory (entry) {
+/**
+ * Saves the historySet entries to a history file.
+ */
+function writeHistoryToFile() {
try {
- historyStream.write(`${entry}\n`)
+ if (isHistoryFileWriteable()) {
+ const data = Array.from(historySet).join('\n') + '\n'
+ fs.writeFileSync(options.historyFile, data)
+ logger.verbose({
+ component:component,
+ message: `history file overwritten with history data from memory`,
+ file: options.historyFile
+ })
+ }
+ else {
+ logger.warn({
+ component,
+ message: 'history file is not writable, scan history will not be flushed',
+ file: options.historyFile
+ })
+ }
}
catch (e) {
logger.error({
- component: component,
+ component,
+ message: 'failure writing to history file',
error: serializeError(e)
})
}
}
-function scheduleNextScan(delay = options.scanInterval) {
- setTimeout(() => {
- startScanner().catch(e => {
- logger.error({ component: component, error: serializeError(e) });
- });
- }, delay);
+/**
+ * Test if options.historyFile is readable.
+ * @returns {boolean}
+ */
+function isHistoryFileReadable() {
+ try {
+ fs.accessSync(options.historyFile, fs.constants.R_OK)
+ return true
+ }
+ catch {
+ return false
+ }
+}
- logger.info({
- component: component,
- message: `scan scheduled`,
- path: options.path,
- delay: delay
- });
+/**
+ * Test if options.historyFile is writable.
+ * If options.historyFile does not exist, create it.
+ * @returns {boolean}
+ */
+function isHistoryFileWriteable() {
+ try {
+ if (fs.existsSync(options.historyFile)) {
+ fs.accessSync(options.historyFile, fs.constants.W_OK)
+ }
+ else {
+ fs.closeSync(fs.openSync(options.historyFile, 'w'))
+ }
+ return true
+ }
+ catch {
+ return false
+ }
}
+export {
+ startScanner,
+ initHistory,
+ initScanner,
+ addToHistory,
+ removeFromHistory,
+}
diff --git a/package-lock.json b/package-lock.json
index 7580ddf..be28065 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,37 +9,45 @@
"version": "1.4.1",
"license": "MIT",
"dependencies": {
+ "@nuwcdivnpt/stig-manager-client-modules": "^1.4.1",
"atob": "^2.1.2",
"better-queue": "^3.8.10",
"chokidar": "^3.5.1",
"commander": "^7.2.0",
"dotenv": "^8.2.0",
"fast-glob": "^3.2.5",
- "fast-xml-parser": "^4.0.7",
"got": "^11.8.2",
- "he": "^1.2.0",
"jsonwebtoken": "^9.0.0",
"n-readlines": "^1.0.1",
"prompt-sync": "4.1.6",
"semver": "^7.3.5",
"serialize-error": "^8.0.1",
- "stig-manager-client-modules": "github:nuwcdivnpt/stig-manager-client-modules#semver:^1.0.0",
"winston": "^3.3.3"
},
"bin": {
"stigman-watcher": "index.js"
},
"devDependencies": {
- "esbuild": "^0.20.0"
+ "c8": "^9.1.0",
+ "chai": "^5.0.3",
+ "esbuild": "^0.20.0",
+ "mocha": "^10.2.0",
+ "nodemon": "^3.0.3"
},
"engines": {
"node": ">=14"
}
},
+ "node_modules/@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true
+ },
"node_modules/@colors/colors": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
- "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz",
+ "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==",
"engines": {
"node": ">=0.1.90"
}
@@ -55,9 +63,9 @@
}
},
"node_modules/@esbuild/aix-ppc64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.0.tgz",
- "integrity": "sha512-fGFDEctNh0CcSwsiRPxiaqX0P5rq+AqE0SRhYGZ4PX46Lg1FNR6oCxJghf8YgY0WQEgQuh3lErUFE4KxLeRmmw==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.1.tgz",
+ "integrity": "sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA==",
"cpu": [
"ppc64"
],
@@ -71,9 +79,9 @@
}
},
"node_modules/@esbuild/android-arm": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.0.tgz",
- "integrity": "sha512-3bMAfInvByLHfJwYPJRlpTeaQA75n8C/QKpEaiS4HrFWFiJlNI0vzq/zCjBrhAYcPyVPG7Eo9dMrcQXuqmNk5g==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.1.tgz",
+ "integrity": "sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw==",
"cpu": [
"arm"
],
@@ -87,9 +95,9 @@
}
},
"node_modules/@esbuild/android-arm64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.0.tgz",
- "integrity": "sha512-aVpnM4lURNkp0D3qPoAzSG92VXStYmoVPOgXveAUoQBWRSuQzt51yvSju29J6AHPmwY1BjH49uR29oyfH1ra8Q==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.1.tgz",
+ "integrity": "sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A==",
"cpu": [
"arm64"
],
@@ -103,9 +111,9 @@
}
},
"node_modules/@esbuild/android-x64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.0.tgz",
- "integrity": "sha512-uK7wAnlRvjkCPzh8jJ+QejFyrP8ObKuR5cBIsQZ+qbMunwR8sbd8krmMbxTLSrDhiPZaJYKQAU5Y3iMDcZPhyQ==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.1.tgz",
+ "integrity": "sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA==",
"cpu": [
"x64"
],
@@ -119,9 +127,9 @@
}
},
"node_modules/@esbuild/darwin-arm64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.0.tgz",
- "integrity": "sha512-AjEcivGAlPs3UAcJedMa9qYg9eSfU6FnGHJjT8s346HSKkrcWlYezGE8VaO2xKfvvlZkgAhyvl06OJOxiMgOYQ==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.1.tgz",
+ "integrity": "sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA==",
"cpu": [
"arm64"
],
@@ -135,9 +143,9 @@
}
},
"node_modules/@esbuild/darwin-x64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.0.tgz",
- "integrity": "sha512-bsgTPoyYDnPv8ER0HqnJggXK6RyFy4PH4rtsId0V7Efa90u2+EifxytE9pZnsDgExgkARy24WUQGv9irVbTvIw==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.1.tgz",
+ "integrity": "sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA==",
"cpu": [
"x64"
],
@@ -151,9 +159,9 @@
}
},
"node_modules/@esbuild/freebsd-arm64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.0.tgz",
- "integrity": "sha512-kQ7jYdlKS335mpGbMW5tEe3IrQFIok9r84EM3PXB8qBFJPSc6dpWfrtsC/y1pyrz82xfUIn5ZrnSHQQsd6jebQ==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.1.tgz",
+ "integrity": "sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw==",
"cpu": [
"arm64"
],
@@ -167,9 +175,9 @@
}
},
"node_modules/@esbuild/freebsd-x64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.0.tgz",
- "integrity": "sha512-uG8B0WSepMRsBNVXAQcHf9+Ko/Tr+XqmK7Ptel9HVmnykupXdS4J7ovSQUIi0tQGIndhbqWLaIL/qO/cWhXKyQ==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.1.tgz",
+ "integrity": "sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg==",
"cpu": [
"x64"
],
@@ -183,9 +191,9 @@
}
},
"node_modules/@esbuild/linux-arm": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.0.tgz",
- "integrity": "sha512-2ezuhdiZw8vuHf1HKSf4TIk80naTbP9At7sOqZmdVwvvMyuoDiZB49YZKLsLOfKIr77+I40dWpHVeY5JHpIEIg==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.1.tgz",
+ "integrity": "sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw==",
"cpu": [
"arm"
],
@@ -199,9 +207,9 @@
}
},
"node_modules/@esbuild/linux-arm64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.0.tgz",
- "integrity": "sha512-uTtyYAP5veqi2z9b6Gr0NUoNv9F/rOzI8tOD5jKcCvRUn7T60Bb+42NDBCWNhMjkQzI0qqwXkQGo1SY41G52nw==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.1.tgz",
+ "integrity": "sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w==",
"cpu": [
"arm64"
],
@@ -215,9 +223,9 @@
}
},
"node_modules/@esbuild/linux-ia32": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.0.tgz",
- "integrity": "sha512-c88wwtfs8tTffPaoJ+SQn3y+lKtgTzyjkD8NgsyCtCmtoIC8RDL7PrJU05an/e9VuAke6eJqGkoMhJK1RY6z4w==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.1.tgz",
+ "integrity": "sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw==",
"cpu": [
"ia32"
],
@@ -231,9 +239,9 @@
}
},
"node_modules/@esbuild/linux-loong64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.0.tgz",
- "integrity": "sha512-lR2rr/128/6svngnVta6JN4gxSXle/yZEZL3o4XZ6esOqhyR4wsKyfu6qXAL04S4S5CgGfG+GYZnjFd4YiG3Aw==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.1.tgz",
+ "integrity": "sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA==",
"cpu": [
"loong64"
],
@@ -247,9 +255,9 @@
}
},
"node_modules/@esbuild/linux-mips64el": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.0.tgz",
- "integrity": "sha512-9Sycc+1uUsDnJCelDf6ZNqgZQoK1mJvFtqf2MUz4ujTxGhvCWw+4chYfDLPepMEvVL9PDwn6HrXad5yOrNzIsQ==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.1.tgz",
+ "integrity": "sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA==",
"cpu": [
"mips64el"
],
@@ -263,9 +271,9 @@
}
},
"node_modules/@esbuild/linux-ppc64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.0.tgz",
- "integrity": "sha512-CoWSaaAXOZd+CjbUTdXIJE/t7Oz+4g90A3VBCHLbfuc5yUQU/nFDLOzQsN0cdxgXd97lYW/psIIBdjzQIwTBGw==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.1.tgz",
+ "integrity": "sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw==",
"cpu": [
"ppc64"
],
@@ -279,9 +287,9 @@
}
},
"node_modules/@esbuild/linux-riscv64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.0.tgz",
- "integrity": "sha512-mlb1hg/eYRJUpv8h/x+4ShgoNLL8wgZ64SUr26KwglTYnwAWjkhR2GpoKftDbPOCnodA9t4Y/b68H4J9XmmPzA==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.1.tgz",
+ "integrity": "sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg==",
"cpu": [
"riscv64"
],
@@ -295,9 +303,9 @@
}
},
"node_modules/@esbuild/linux-s390x": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.0.tgz",
- "integrity": "sha512-fgf9ubb53xSnOBqyvWEY6ukBNRl1mVX1srPNu06B6mNsNK20JfH6xV6jECzrQ69/VMiTLvHMicQR/PgTOgqJUQ==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.1.tgz",
+ "integrity": "sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ==",
"cpu": [
"s390x"
],
@@ -311,9 +319,9 @@
}
},
"node_modules/@esbuild/linux-x64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.0.tgz",
- "integrity": "sha512-H9Eu6MGse++204XZcYsse1yFHmRXEWgadk2N58O/xd50P9EvFMLJTQLg+lB4E1cF2xhLZU5luSWtGTb0l9UeSg==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz",
+ "integrity": "sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==",
"cpu": [
"x64"
],
@@ -327,9 +335,9 @@
}
},
"node_modules/@esbuild/netbsd-x64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.0.tgz",
- "integrity": "sha512-lCT675rTN1v8Fo+RGrE5KjSnfY0x9Og4RN7t7lVrN3vMSjy34/+3na0q7RIfWDAj0e0rCh0OL+P88lu3Rt21MQ==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.1.tgz",
+ "integrity": "sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg==",
"cpu": [
"x64"
],
@@ -343,9 +351,9 @@
}
},
"node_modules/@esbuild/openbsd-x64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.0.tgz",
- "integrity": "sha512-HKoUGXz/TOVXKQ+67NhxyHv+aDSZf44QpWLa3I1lLvAwGq8x1k0T+e2HHSRvxWhfJrFxaaqre1+YyzQ99KixoA==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.1.tgz",
+ "integrity": "sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw==",
"cpu": [
"x64"
],
@@ -359,9 +367,9 @@
}
},
"node_modules/@esbuild/sunos-x64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.0.tgz",
- "integrity": "sha512-GDwAqgHQm1mVoPppGsoq4WJwT3vhnz/2N62CzhvApFD1eJyTroob30FPpOZabN+FgCjhG+AgcZyOPIkR8dfD7g==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.1.tgz",
+ "integrity": "sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q==",
"cpu": [
"x64"
],
@@ -375,9 +383,9 @@
}
},
"node_modules/@esbuild/win32-arm64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.0.tgz",
- "integrity": "sha512-0vYsP8aC4TvMlOQYozoksiaxjlvUcQrac+muDqj1Fxy6jh9l9CZJzj7zmh8JGfiV49cYLTorFLxg7593pGldwQ==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.1.tgz",
+ "integrity": "sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A==",
"cpu": [
"arm64"
],
@@ -391,9 +399,9 @@
}
},
"node_modules/@esbuild/win32-ia32": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.0.tgz",
- "integrity": "sha512-p98u4rIgfh4gdpV00IqknBD5pC84LCub+4a3MO+zjqvU5MVXOc3hqR2UgT2jI2nh3h8s9EQxmOsVI3tyzv1iFg==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.1.tgz",
+ "integrity": "sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw==",
"cpu": [
"ia32"
],
@@ -407,9 +415,9 @@
}
},
"node_modules/@esbuild/win32-x64": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.0.tgz",
- "integrity": "sha512-NgJnesu1RtWihtTtXGFMU5YSE6JyyHPMxCwBZK7a6/8d31GuSo9l0Ss7w1Jw5QnKUawG6UEehs883kcXf5fYwg==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.1.tgz",
+ "integrity": "sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==",
"cpu": [
"x64"
],
@@ -422,6 +430,40 @@
"node": ">=12"
}
},
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.23",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.23.tgz",
+ "integrity": "sha512-9/4foRoUKp8s96tSkh8DlAAc5A0Ty8vLXld+l9gjKKY6ckwI8G15f0hskGmuLZu78ZlGa1vtsfOa+lnB4vG6Jg==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -454,6 +496,12 @@
"node": ">= 8"
}
},
+ "node_modules/@nuwcdivnpt/stig-manager-client-modules": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@nuwcdivnpt/stig-manager-client-modules/-/stig-manager-client-modules-1.4.1.tgz",
+ "integrity": "sha512-Zd0l9v4JdjnmCtMGPlj7d3vuA7iwXWW6Cw91pKopC6RG6Pf0uL5HhF2FOKNJUgqa4drrlAl5/lFI8aRYK30cag==",
+ "hasInstallScript": true
+ },
"node_modules/@sindresorhus/is": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
@@ -488,9 +536,15 @@
}
},
"node_modules/@types/http-cache-semantics": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
- "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ=="
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz",
+ "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA=="
+ },
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
+ "dev": true
},
"node_modules/@types/keyv": {
"version": "3.1.4",
@@ -501,18 +555,65 @@
}
},
"node_modules/@types/node": {
- "version": "18.11.17",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.17.tgz",
- "integrity": "sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng=="
+ "version": "20.11.22",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.22.tgz",
+ "integrity": "sha512-/G+IxWxma6V3E+pqK1tSl2Fo1kl41pK1yeCyDsgkF9WlVAme4j5ISYM2zR11bgLFJGLN5sVK40T4RJNuiZbEjA==",
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
},
"node_modules/@types/responselike": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz",
- "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz",
+ "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==",
"dependencies": {
"@types/node": "*"
}
},
+ "node_modules/@types/triple-beam": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
+ "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw=="
+ },
+ "node_modules/abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "dev": true
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
@@ -525,10 +626,25 @@
"node": ">= 8"
}
},
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/assertion-error": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
+ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/async": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
- "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
+ "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg=="
},
"node_modules/atob": {
"version": "2.1.2",
@@ -541,6 +657,12 @@
"node": ">= 4.5.0"
}
},
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
"node_modules/better-queue": {
"version": "3.8.12",
"resolved": "https://registry.npmjs.org/better-queue/-/better-queue-3.8.12.tgz",
@@ -564,6 +686,15 @@
"node": ">=8"
}
},
+ "node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
"node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
@@ -575,11 +706,42 @@
"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==",
+ "dev": true
+ },
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
},
+ "node_modules/c8": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/c8/-/c8-9.1.0.tgz",
+ "integrity": "sha512-mBWcT5iqNir1zIkzSPyI3NCR9EZCVI3WUD+AVO17MVWTSFNyUueXE82qTeampNtTr+ilN/5Ua3j24LgbCKjDVg==",
+ "dev": true,
+ "dependencies": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@istanbuljs/schema": "^0.1.3",
+ "find-up": "^5.0.0",
+ "foreground-child": "^3.1.1",
+ "istanbul-lib-coverage": "^3.2.0",
+ "istanbul-lib-report": "^3.0.1",
+ "istanbul-reports": "^3.1.6",
+ "test-exclude": "^6.0.0",
+ "v8-to-istanbul": "^9.0.0",
+ "yargs": "^17.7.2",
+ "yargs-parser": "^21.1.1"
+ },
+ "bin": {
+ "c8": "bin/c8.js"
+ },
+ "engines": {
+ "node": ">=14.14.0"
+ }
+ },
"node_modules/cacheable-lookup": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
@@ -589,9 +751,9 @@
}
},
"node_modules/cacheable-request": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz",
- "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==",
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz",
+ "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==",
"dependencies": {
"clone-response": "^1.0.2",
"get-stream": "^5.1.0",
@@ -605,16 +767,63 @@
"node": ">=8"
}
},
+ "node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/chai": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.0.tgz",
+ "integrity": "sha512-kDZ7MZyM6Q1DhR9jy7dalKohXQ2yrlXkk59CR52aRKxJrobmlBNqnFQxX9xOX8w+4mz8SYlKJa/7D7ddltFXCw==",
+ "dev": true,
+ "dependencies": {
+ "assertion-error": "^2.0.1",
+ "check-error": "^2.0.0",
+ "deep-eql": "^5.0.1",
+ "loupe": "^3.1.0",
+ "pathval": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/check-error": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.0.0.tgz",
+ "integrity": "sha512-tjLAOBHKVxtPoHe/SA7kNOMvhCRdCJ3vETdeY0RuAc9popf+hyaSV6ZEg9hr4cpWF7jmo/JSWEnLDrnijS9Tog==",
+ "dev": true,
+ "engines": {
+ "node": ">= 16"
+ }
+ },
"node_modules/chokidar": {
- "version": "3.5.3",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
- "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
- "funding": [
- {
- "type": "individual",
- "url": "https://paulmillr.com/funding/"
- }
- ],
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
@@ -627,10 +836,27 @@
"engines": {
"node": ">= 8.10.0"
},
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/clone-response": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
@@ -652,17 +878,21 @@
}
},
"node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
"dependencies": {
- "color-name": "1.1.3"
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
}
},
"node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ "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/color-string": {
"version": "1.9.1",
@@ -673,6 +903,19 @@
"simple-swizzle": "^0.2.2"
}
},
+ "node_modules/color/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ },
"node_modules/colorspace": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz",
@@ -690,6 +933,67 @@
"node": ">= 10"
}
},
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/debug/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/decamelize": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/decompress-response": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
@@ -715,6 +1019,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/deep-eql": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.1.tgz",
+ "integrity": "sha512-nwQCf6ne2gez3o1MxWifqkciwt0zhl0LO1/UwVu4uMBuPmflWM4oQ70XMqHqnBJA+nhzncaqL9HVL6KkHJ28lw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/defer-to-connect": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
@@ -723,6 +1036,15 @@
"node": ">=10"
}
},
+ "node_modules/diff": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
"node_modules/dotenv": {
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz",
@@ -739,6 +1061,12 @@
"safe-buffer": "^5.0.1"
}
},
+ "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==",
+ "dev": true
+ },
"node_modules/enabled": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
@@ -753,9 +1081,9 @@
}
},
"node_modules/esbuild": {
- "version": "0.20.0",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.0.tgz",
- "integrity": "sha512-6iwE3Y2RVYCME1jLpBqq7LQWK3MW6vjV2bZy6gt/WrqkY+WE74Spyc0ThAOYpMtITvnjX09CrC6ym7A/m9mebA==",
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz",
+ "integrity": "sha512-OJwEgrpWm/PCMsLVWXKqvcjme3bHNpOgN7Tb6cQnR5n0TPbQx1/Xrn7rqM+wn17bYeT6MGB5sn1Bh5YiGi70nA==",
"dev": true,
"hasInstallScript": true,
"bin": {
@@ -765,35 +1093,56 @@
"node": ">=12"
},
"optionalDependencies": {
- "@esbuild/aix-ppc64": "0.20.0",
- "@esbuild/android-arm": "0.20.0",
- "@esbuild/android-arm64": "0.20.0",
- "@esbuild/android-x64": "0.20.0",
- "@esbuild/darwin-arm64": "0.20.0",
- "@esbuild/darwin-x64": "0.20.0",
- "@esbuild/freebsd-arm64": "0.20.0",
- "@esbuild/freebsd-x64": "0.20.0",
- "@esbuild/linux-arm": "0.20.0",
- "@esbuild/linux-arm64": "0.20.0",
- "@esbuild/linux-ia32": "0.20.0",
- "@esbuild/linux-loong64": "0.20.0",
- "@esbuild/linux-mips64el": "0.20.0",
- "@esbuild/linux-ppc64": "0.20.0",
- "@esbuild/linux-riscv64": "0.20.0",
- "@esbuild/linux-s390x": "0.20.0",
- "@esbuild/linux-x64": "0.20.0",
- "@esbuild/netbsd-x64": "0.20.0",
- "@esbuild/openbsd-x64": "0.20.0",
- "@esbuild/sunos-x64": "0.20.0",
- "@esbuild/win32-arm64": "0.20.0",
- "@esbuild/win32-ia32": "0.20.0",
- "@esbuild/win32-x64": "0.20.0"
+ "@esbuild/aix-ppc64": "0.20.1",
+ "@esbuild/android-arm": "0.20.1",
+ "@esbuild/android-arm64": "0.20.1",
+ "@esbuild/android-x64": "0.20.1",
+ "@esbuild/darwin-arm64": "0.20.1",
+ "@esbuild/darwin-x64": "0.20.1",
+ "@esbuild/freebsd-arm64": "0.20.1",
+ "@esbuild/freebsd-x64": "0.20.1",
+ "@esbuild/linux-arm": "0.20.1",
+ "@esbuild/linux-arm64": "0.20.1",
+ "@esbuild/linux-ia32": "0.20.1",
+ "@esbuild/linux-loong64": "0.20.1",
+ "@esbuild/linux-mips64el": "0.20.1",
+ "@esbuild/linux-ppc64": "0.20.1",
+ "@esbuild/linux-riscv64": "0.20.1",
+ "@esbuild/linux-s390x": "0.20.1",
+ "@esbuild/linux-x64": "0.20.1",
+ "@esbuild/netbsd-x64": "0.20.1",
+ "@esbuild/openbsd-x64": "0.20.1",
+ "@esbuild/sunos-x64": "0.20.1",
+ "@esbuild/win32-arm64": "0.20.1",
+ "@esbuild/win32-ia32": "0.20.1",
+ "@esbuild/win32-x64": "0.20.1"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
+ "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/fast-glob": {
- "version": "3.2.12",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
- "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
@@ -805,31 +1154,10 @@
"node": ">=8.6.0"
}
},
- "node_modules/fast-xml-parser": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.3.tgz",
- "integrity": "sha512-coV/D1MhrShMvU6D0I+VAK3umz6hUaxxhL0yp/9RjfiYUfAv14rDhGQL+PLForhMdr0wq3PiV07WtkkNjJjNHg==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/NaturalIntelligence"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/naturalintelligence"
- }
- ],
- "dependencies": {
- "strnum": "^1.0.5"
- },
- "bin": {
- "fxparser": "src/cli/cli.js"
- }
- },
"node_modules/fastq": {
- "version": "1.14.0",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz",
- "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==",
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
"dependencies": {
"reusify": "^1.0.4"
}
@@ -850,11 +1178,89 @@
"node": ">=8"
}
},
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true,
+ "bin": {
+ "flat": "cli.js"
+ }
+ },
"node_modules/fn.name": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
+ "node_modules/foreground-child": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
+ "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-func-name": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
+ "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
@@ -869,6 +1275,25 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
@@ -904,14 +1329,30 @@
"url": "https://github.com/sindresorhus/got?sponsor=1"
}
},
- "node_modules/he": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
"bin": {
"he": "bin/he"
}
},
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true
+ },
"node_modules/http-cache-semantics": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
@@ -929,6 +1370,22 @@
"node": ">=10.19.0"
}
},
+ "node_modules/ignore-by-default": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
+ "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
+ "dev": true
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
@@ -958,6 +1415,15 @@
"node": ">=0.10.0"
}
},
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -977,6 +1443,15 @@
"node": ">=0.12.0"
}
},
+ "node_modules/is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
@@ -988,20 +1463,92 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+ "dev": true,
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
+ "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==",
+ "dev": true,
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
"node_modules/json-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
},
"node_modules/jsonwebtoken": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz",
- "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==",
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
+ "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
"dependencies": {
"jws": "^3.2.2",
- "lodash": "^4.17.21",
+ "lodash.includes": "^4.3.0",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isinteger": "^4.0.4",
+ "lodash.isnumber": "^3.0.3",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.once": "^4.0.0",
"ms": "^2.1.1",
- "semver": "^7.3.8"
+ "semver": "^7.5.4"
},
"engines": {
"node": ">=12",
@@ -1028,9 +1575,9 @@
}
},
"node_modules/keyv": {
- "version": "4.5.2",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz",
- "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==",
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
"dependencies": {
"json-buffer": "3.0.1"
}
@@ -1040,21 +1587,95 @@
"resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
"integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
},
- "node_modules/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="
+ },
+ "node_modules/lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
+ },
+ "node_modules/lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="
+ },
+ "node_modules/lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="
+ },
+ "node_modules/lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
+ },
+ "node_modules/lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
+ },
+ "node_modules/lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
+ },
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
},
"node_modules/logform": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/logform/-/logform-2.4.2.tgz",
- "integrity": "sha512-W4c9himeAwXEdZ05dQNerhFz2XG80P9Oj0loPUMV23VC2it0orMHQhJm4hdnnor3rd1HsGf6a2lPwBM1zeXHGw==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz",
+ "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==",
"dependencies": {
- "@colors/colors": "1.5.0",
+ "@colors/colors": "1.6.0",
+ "@types/triple-beam": "^1.3.2",
"fecha": "^4.2.0",
"ms": "^2.1.1",
"safe-stable-stringify": "^2.3.1",
"triple-beam": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
+ "node_modules/loupe": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.0.tgz",
+ "integrity": "sha512-qKl+FrLXUhFuHUoDJG7f8P8gEMHq9NFS0c6ghXG1J0rldmZFQZoNVv/vyirE9qwCIhWZDsvEFd1sbFu3GvRQFg==",
+ "dev": true,
+ "dependencies": {
+ "get-func-name": "^2.0.1"
}
},
"node_modules/lowercase-keys": {
@@ -1076,6 +1697,21 @@
"node": ">=10"
}
},
+ "node_modules/make-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -1104,6 +1740,133 @@
"node": ">=4"
}
},
+ "node_modules/minimatch": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+ "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mocha": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.3.0.tgz",
+ "integrity": "sha512-uF2XJs+7xSLsrmIvn37i/wnc91nw7XjOQB8ccyx5aEgdnohr7n+rEiZP23WkCYHjilR6+EboEnbq/ZQDz4LSbg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-colors": "4.1.1",
+ "browser-stdout": "1.3.1",
+ "chokidar": "3.5.3",
+ "debug": "4.3.4",
+ "diff": "5.0.0",
+ "escape-string-regexp": "4.0.0",
+ "find-up": "5.0.0",
+ "glob": "8.1.0",
+ "he": "1.2.0",
+ "js-yaml": "4.1.0",
+ "log-symbols": "4.1.0",
+ "minimatch": "5.0.1",
+ "ms": "2.1.3",
+ "serialize-javascript": "6.0.0",
+ "strip-json-comments": "3.1.1",
+ "supports-color": "8.1.1",
+ "workerpool": "6.2.1",
+ "yargs": "16.2.0",
+ "yargs-parser": "20.2.4",
+ "yargs-unparser": "2.0.0"
+ },
+ "bin": {
+ "_mocha": "bin/_mocha",
+ "mocha": "bin/mocha.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/mocha/node_modules/chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/mocha/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==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "node_modules/mocha/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/mocha/node_modules/yargs": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^20.2.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mocha/node_modules/yargs-parser": {
+ "version": "20.2.4",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+ "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -1122,6 +1885,92 @@
"resolved": "https://registry.npmjs.org/node-eta/-/node-eta-0.9.0.tgz",
"integrity": "sha512-mTCTZk29tmX1OGfVkPt63H3c3VqXrI2Kvua98S7iUIB/Gbp0MNw05YtUomxQIxnnKMyRIIuY9izPcFixzhSBrA=="
},
+ "node_modules/nodemon": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz",
+ "integrity": "sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==",
+ "dev": true,
+ "dependencies": {
+ "chokidar": "^3.5.2",
+ "debug": "^4",
+ "ignore-by-default": "^1.0.1",
+ "minimatch": "^3.1.2",
+ "pstree.remy": "^1.1.8",
+ "semver": "^7.5.3",
+ "simple-update-notifier": "^2.0.0",
+ "supports-color": "^5.5.0",
+ "touch": "^3.1.0",
+ "undefsafe": "^2.0.5"
+ },
+ "bin": {
+ "nodemon": "bin/nodemon.js"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/nodemon"
+ }
+ },
+ "node_modules/nodemon/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/nodemon/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/nodemon/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/nodemon/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==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/nopt": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
+ "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
+ "dev": true,
+ "dependencies": {
+ "abbrev": "1"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -1165,6 +2014,72 @@
"node": ">=8"
}
},
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pathval": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz",
+ "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 14.16"
+ }
+ },
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
@@ -1181,6 +2096,12 @@
"resolved": "https://registry.npmjs.org/prompt-sync/-/prompt-sync-4.1.6.tgz",
"integrity": "sha512-dYjDha0af2vefm6soqnPnFEz2tAzwH/kb+pPoaCohRoPUxFXj+mymkOFgxX7Ylv59TdEr7OzktEizdK7MIMvIw=="
},
+ "node_modules/pstree.remy": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
+ "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
+ "dev": true
+ },
"node_modules/pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
@@ -1220,10 +2141,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
"node_modules/readable-stream": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
- "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
@@ -1244,6 +2174,15 @@
"node": ">=8.10.0"
}
},
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/resolve-alpn": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
@@ -1311,17 +2250,17 @@
]
},
"node_modules/safe-stable-stringify": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.1.tgz",
- "integrity": "sha512-dVHE6bMtS/bnL2mwualjc6IxEv1F+OCUpA46pKUj6F8uDbUM0jCCulPqRNPSnWwGNKx5etqMjZYdXtrm5KJZGA==",
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz",
+ "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==",
"engines": {
"node": ">=10"
}
},
"node_modules/semver": {
- "version": "7.5.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
- "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+ "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
"dependencies": {
"lru-cache": "^6.0.0"
},
@@ -1346,6 +2285,48 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/serialize-javascript": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+ "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+ "dev": true,
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
@@ -1354,6 +2335,18 @@
"is-arrayish": "^0.3.1"
}
},
+ "node_modules/simple-update-notifier": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
+ "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/stack-trace": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
@@ -1362,15 +2355,6 @@
"node": "*"
}
},
- "node_modules/stig-manager-client-modules": {
- "version": "1.0.0",
- "resolved": "git+ssh://git@github.com/nuwcdivnpt/stig-manager-client-modules.git#dc3732b2b7e2360813ce057e34a4de040ee26173",
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "fast-xml-parser": "^4.3.2"
- }
- },
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
@@ -1379,10 +2363,111 @@
"safe-buffer": "~5.2.0"
}
},
- "node_modules/strnum": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
- "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/test-exclude/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/test-exclude/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/test-exclude/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
},
"node_modules/text-hex": {
"version": "1.0.0",
@@ -1400,10 +2485,25 @@
"node": ">=8.0"
}
},
+ "node_modules/touch": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
+ "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
+ "dev": true,
+ "dependencies": {
+ "nopt": "~1.0.10"
+ },
+ "bin": {
+ "nodetouch": "bin/nodetouch.js"
+ }
+ },
"node_modules/triple-beam": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
- "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw=="
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz",
+ "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==",
+ "engines": {
+ "node": ">= 14.0.0"
+ }
},
"node_modules/type-fest": {
"version": "0.20.2",
@@ -1416,25 +2516,69 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/undefsafe": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
+ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
+ "dev": true
+ },
+ "node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/uuid": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
- "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
"bin": {
"uuid": "dist/bin/uuid"
}
},
+ "node_modules/v8-to-istanbul": {
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz",
+ "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.12",
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
"node_modules/winston": {
- "version": "3.8.2",
- "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz",
- "integrity": "sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==",
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/winston/-/winston-3.11.0.tgz",
+ "integrity": "sha512-L3yR6/MzZAOl0DsysUXHVjOwv8mKZ71TrA/41EIduGpOOV5LQVodqN+QdQ6BS6PJ/RdIshZhq84P/fStEZkk7g==",
"dependencies": {
- "@colors/colors": "1.5.0",
+ "@colors/colors": "^1.6.0",
"@dabh/diagnostics": "^2.0.2",
"async": "^3.2.3",
"is-stream": "^2.0.0",
@@ -1451,16 +2595,39 @@
}
},
"node_modules/winston-transport": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz",
- "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==",
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz",
+ "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==",
"dependencies": {
"logform": "^2.3.2",
"readable-stream": "^3.6.0",
"triple-beam": "^1.3.0"
},
"engines": {
- "node": ">= 6.4.0"
+ "node": ">= 12.0.0"
+ }
+ },
+ "node_modules/workerpool": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
+ "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "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/wrappy": {
@@ -1468,10 +2635,73 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
"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": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "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.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-unparser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
}
}
}
diff --git a/package.json b/package.json
index 97f7979..8511b76 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,10 @@
"bin": {
"stigman-watcher": "index.js"
},
+ "scripts": {
+ "test": "c8 --reporter=html --reporter=text mocha './test/**/*.test.js'",
+ "test:watch": "nodemon --ext 'js' --exec 'npm test'"
+ },
"type": "module",
"author": "carl.a.smigielski@saic.com",
"license": "MIT",
@@ -17,24 +21,26 @@
"node": ">=14"
},
"dependencies": {
+ "@nuwcdivnpt/stig-manager-client-modules": "^1.4.1",
"atob": "^2.1.2",
"better-queue": "^3.8.10",
"chokidar": "^3.5.1",
"commander": "^7.2.0",
"dotenv": "^8.2.0",
"fast-glob": "^3.2.5",
- "fast-xml-parser": "^4.0.7",
"got": "^11.8.2",
- "he": "^1.2.0",
"jsonwebtoken": "^9.0.0",
"n-readlines": "^1.0.1",
"prompt-sync": "4.1.6",
"semver": "^7.3.5",
"serialize-error": "^8.0.1",
- "stig-manager-client-modules": "github:nuwcdivnpt/stig-manager-client-modules#semver:^1.0.0",
"winston": "^3.3.3"
},
"devDependencies": {
- "esbuild": "^0.20.0"
+ "c8": "^9.1.0",
+ "chai": "^5.0.3",
+ "esbuild": "^0.20.0",
+ "mocha": "^10.2.0",
+ "nodemon": "^3.0.3"
}
}
diff --git a/test/scan/historyfile.test.js b/test/scan/historyfile.test.js
new file mode 100644
index 0000000..28278b2
--- /dev/null
+++ b/test/scan/historyfile.test.js
@@ -0,0 +1,247 @@
+import { expect } from 'chai'
+import fs from 'fs'
+import { initHistory, addToHistory, removeFromHistory } from '../../lib/scan.js'
+import { logger } from '../../lib/logger.js'
+import path from 'path'
+import { options } from '../../lib/args.js'
+
+const emptyFn = () => undefined
+for (const method of ['info', 'warn', 'error', 'verbose', 'debug', 'silly', 'http']) {
+ logger[method] = emptyFn
+}
+
+function setOptions (o) {
+ for (const [key, value] of Object.entries(o)) {
+ options[key] = value
+ }
+}
+
+describe('testing add/remove/init functions ', function () {
+ const historyFile = './watcher.test.history'
+ const scannedPath = './test/testFiles/TestScannedDirectory'
+
+ beforeEach(function () {
+ fs.writeFileSync(historyFile, '')
+ })
+
+ afterEach(function () {
+ fs.unlinkSync(historyFile)
+ })
+
+ it('should correctly create an empty history file', async function () {
+ setOptions({
+ historyFile: historyFile,
+ path: scannedPath,
+ scanInterval: 15000,
+ oneShot: true,
+ historyWriteInterval: 10
+ })
+ initHistory()
+ expect(fs.existsSync(historyFile)).to.be.true
+ expect(fs.readFileSync(historyFile, 'utf8')).to.equal('')
+ })
+
+ it('should correctly add to history file', async function () {
+ setOptions({
+ historyFile: historyFile,
+ path: scannedPath,
+ scanInterval: 5000,
+ oneShot: true,
+ historyWriteInterval: 10
+ })
+
+ initHistory()
+
+ const file = './test/testFiles/file1.ckl'
+
+ addToHistory(file)
+
+ await new Promise(resolve => setTimeout(resolve, options.historyWriteInterval))
+ const data = fs.readFileSync(historyFile, 'utf8').trim() // Trim the newline character
+ expect(data).to.equal(file)
+ })
+
+ it('should correctly remove from history file', async function () {
+ setOptions({
+ historyFile: historyFile,
+ path: scannedPath,
+ scanInterval: 5000,
+ oneShot: true,
+ historyWriteInterval: 10
+ })
+
+ initHistory(options)
+
+ const file = './test/testFiles/file1.ckl'
+
+ addToHistory(file)
+
+ await new Promise(resolve => setTimeout(resolve, options.historyWriteInterval))
+
+ removeFromHistory(file)
+
+ await new Promise(resolve => setTimeout(resolve, options.historyWriteInterval))
+
+ const data = fs.readFileSync(historyFile, 'utf8').trim()
+
+ expect(data).to.equal('')
+ })
+})
+
+describe('testing starting with empty history file and adding entries', function () {
+ const historyFile = './watcher.test.history'
+ const scannedPath = './test/testFiles/'
+ const fileContents = ''
+ beforeEach(function () {
+ fs.writeFileSync(historyFile, '')
+ fs.mkdirSync(scannedPath, { recursive: true })
+ for (let i = 1; i <= 5; i++) {
+ fs.writeFileSync(path.join(scannedPath, `file${i}.ckl`), fileContents)
+ }
+ })
+
+ afterEach(function () {
+ fs.unlinkSync(historyFile)
+
+ const files = fs.readdirSync(scannedPath)
+ for (const file of files) {
+ fs.unlinkSync(path.join(scannedPath, file))
+ }
+ fs.rmSync(scannedPath, { recursive: true })
+ })
+
+ it('should correctly identify the 5 new files and update the history file with all 5', async function () {
+ setOptions({
+ historyFile: historyFile,
+ path: scannedPath,
+ scanInterval: 5000,
+ oneShot: true,
+ historyWriteInterval: 10
+ })
+
+ // create history file
+ initHistory()
+
+
+ const files = fs.readdirSync(scannedPath)
+ for (const file of files) {
+ addToHistory(path.join(scannedPath, file))
+ }
+
+
+ await new Promise(resolve =>
+ setTimeout(resolve, options.historyWriteInterval)
+ )
+
+ // read the history file
+ const data = fs.readFileSync(historyFile, 'utf8')
+ const lines = data.split('\n').filter(line => line.trim() !== '')
+
+ expect(lines.length).to.equal(5)
+
+ const expectedHistoryEntries = [
+ 'test/testFiles/file1.ckl',
+ 'test/testFiles/file2.ckl',
+ 'test/testFiles/file3.ckl',
+ 'test/testFiles/file4.ckl',
+ 'test/testFiles/file5.ckl'
+ ]
+
+ for (const entry of expectedHistoryEntries) {
+ expect(lines).to.include(entry)
+ }
+ })
+})
+
+describe('testing starting with empty history file and slowly adding and removing items to history manually', function () {
+ this.timeout(5000)
+ const historyFile = './watcher.test.history'
+ const scannedPath = './test/testFiles/'
+
+ beforeEach(function () {
+ fs.writeFileSync(historyFile, '')
+ })
+
+ afterEach(function () {
+ fs.unlinkSync(historyFile)
+ })
+
+ it('should correctly remove the 2 files history file skip 2 files already in the history file and scanned directory and add one file to the history file', async function () {
+ setOptions({
+ historyFile: historyFile,
+ path: scannedPath,
+ scanInterval: 5000,
+ oneShot: true,
+ historyWriteInterval: 50
+ })
+
+ // create history file
+ initHistory()
+
+ addToHistory('./test/testFiles/file1.ckl')
+ addToHistory('./test/testFiles/file2.ckl')
+
+ await new Promise(resolve => setTimeout(resolve, options.historyWriteInterval))
+
+ // read the history file
+ const data = fs.readFileSync(historyFile, 'utf8')
+ const lines = data.split('\n').filter(line => line.trim() !== '')
+
+ expect(lines.length).to.equal(2)
+ expect(lines).to.include('./test/testFiles/file1.ckl')
+ expect(lines).to.include('./test/testFiles/file2.ckl')
+
+ removeFromHistory('./test/testFiles/file1.ckl')
+
+ await new Promise(resolve => setTimeout(resolve, options.historyWriteInterval))
+
+ // read the history file
+ const data2 = fs.readFileSync(historyFile, 'utf8')
+ const lines2 = data2.split('\n').filter(line => line.trim() !== '')
+
+ expect(lines2.length).to.equal(1)
+ expect(lines2).to.include('./test/testFiles/file2.ckl')
+ })
+})
+
+describe('testing no history file mode', function () {
+ const historyFile = null
+ const scannedPath = './test/testFiles/'
+
+ it('should correctly run in no history file mode', async function () {
+ setOptions({
+ historyFile: historyFile,
+ path: scannedPath,
+ scanInterval: 5000,
+ oneShot: true,
+ historyWriteInterval: 10
+ })
+
+ initHistory()
+
+ const file = './test/testFiles/file1.ckl'
+
+ addToHistory(file)
+
+ await new Promise(resolve => setTimeout(resolve, options.historyWriteInterval))
+
+ // expect no history file to be created
+ expect(fs.existsSync(historyFile)).to.be.false
+ })
+})
+
+describe('cleaning up', function () {
+ after(async function () {
+ setTimeout(() => {
+ process.exit(0) // Delayed exit to allow Mocha to output results
+ }, 1000) // Adjust time as necessary for your environment
+ })
+
+ it('should clean up the history file', function () {
+ const historyFilePath = './watcher.test.history'
+ // Check if the file exists and delete it
+ if (fs.existsSync(historyFilePath)) {
+ fs.unlinkSync(historyFilePath)
+ }
+ })
+})
From d4ba1e5d3f8e6852cf3a4cc7aa427a952329580a Mon Sep 17 00:00:00 2001
From: csmig
Date: Mon, 4 Mar 2024 15:35:22 -0500
Subject: [PATCH 03/13] 2024-03-04 session
---
index.js | 19 ++++++++++++++--
lib/api.js | 34 +++++++++++++++++++++-------
lib/auth.js | 64 +++++++++++++++++++++++++++--------------------------
lib/scan.js | 52 ++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 127 insertions(+), 42 deletions(-)
diff --git a/index.js b/index.js
index 1596982..8e3527c 100755
--- a/index.js
+++ b/index.js
@@ -12,6 +12,7 @@ import * as api from './lib/api.js'
import { serializeError } from 'serialize-error'
import { initScanner } from './lib/scan.js'
import semverGte from 'semver/functions/gte.js'
+import Alarm from './lib/alarm.js'
const minApiVersion = '1.2.7'
@@ -21,9 +22,23 @@ process.on('SIGINT', () => {
message: 'received SIGINT, exiting'
})
process.exit(0)
-})
+})
-run()
+Alarm.on('alarmRaised', (alarmType) => {
+ logger.error({
+ component: 'main',
+ message: `Alarm raised: ${alarmType}`
+ })
+})
+
+Alarm.on('alarmLowered', (alarmType) => {
+ logger.error({
+ component: 'main',
+ message: `Alarm lowered: ${alarmType}`
+ })
+})
+
+await run()
async function run() {
try {
diff --git a/lib/api.js b/lib/api.js
index 00fd696..7754a4c 100644
--- a/lib/api.js
+++ b/lib/api.js
@@ -2,6 +2,7 @@ import got from 'got'
import { options } from './args.js'
import { getToken, tokens } from './auth.js'
import { logger, getSymbol } from './logger.js'
+import Alarm from './alarm.js'
const cache = {
collection: null,
@@ -15,16 +16,26 @@ const _cache = cache
export { _cache as cache }
async function apiGet(endpoint, authenticate = true) {
- try {
- const requestOptions = {
- responseType: 'json'
- }
- if (authenticate) {
+ const requestOptions = {
+ responseType: 'json',
+ timeout: {
+ request: 5000
+ }
+ }
+ if (authenticate) {
+ try {
await getToken()
- requestOptions.headers = {
- Authorization: `Bearer ${tokens.access_token}`
- }
}
+ catch (e) {
+ e.component = 'api'
+ logError(e)
+ throw(e)
+ }
+ requestOptions.headers = {
+ Authorization: `Bearer ${tokens.access_token}`
+ }
+ }
+ try {
const response = await got.get(`${options.api}${endpoint}`, requestOptions)
logResponse (response )
return response.body
@@ -32,6 +43,13 @@ async function apiGet(endpoint, authenticate = true) {
catch (e) {
e.component = 'api'
logError(e)
+ // grant problem
+ if (e.response?.statusCode === 403) {
+ Alarm.noGrant(true)
+ }
+ else {
+ Alarm.apiOffline(true)
+ }
throw (e)
}
}
diff --git a/lib/auth.js b/lib/auth.js
index dd932e2..0d5a0f2 100644
--- a/lib/auth.js
+++ b/lib/auth.js
@@ -4,11 +4,12 @@ import atob from 'atob'
import {options} from './args.js'
import jwt from 'jsonwebtoken'
import { randomBytes } from 'crypto'
+import Alarm from './alarm.js'
const self = {}
self.url = null
-self.threshold = 10
+self.threshold = 10 //seconds!
self.scope = 'openid stig-manager:collection stig-manager:stig:read stig-manager:user:read'
self.key = options.clientKey
self.authenticateFn = options.clientKey ? authenticateSignedJwt : authenticateClientSecret
@@ -23,27 +24,31 @@ let tokens, tokenDecoded
* @throws {Error} - If there's an error fetching the OpenID configuration.
*/
async function getOpenIDConfiguration () {
+ const wellKnownUrl = `${options.authority}/.well-known/openid-configuration`
+ logger.debug({
+ component: 'auth',
+ message: `sending openId configuration request`,
+ request: {
+ method: 'GET',
+ url: wellKnownUrl
+ }
+ })
+ let response
try {
- const wellKnownUrl = `${options.authority}/.well-known/openid-configuration`
- logger.debug({
- component: 'auth',
- message: `sending openId configuration request`,
- request: {
- method: 'GET',
- url: wellKnownUrl
- }
- })
- const response = await got.get(wellKnownUrl, { responseType: 'json' })
- logResponse(response)
- self.url = response.body.token_endpoint
- return response.body
+ response = await got.get(wellKnownUrl, { responseType: 'json' })
}
catch (e) {
if (e.response) {
logResponse(e.response)
}
+ else {
+ Alarm.authOffline(true)
+ }
throw e
}
+ logResponse(response)
+ self.url = response.body.token_endpoint
+ return response.body
}
/**
@@ -54,32 +59,29 @@ async function getOpenIDConfiguration () {
* @throws {Error} If there was an error retrieving the token.
*/
async function getToken () {
+ if (tokenDecoded?.exp - Math.ceil(new Date().getTime() / 1000) >= self.threshold)
+ return tokenDecoded
try {
- if (tokenDecoded) {
- let expiresIn =
- tokenDecoded.exp - Math.ceil(new Date().getTime() / 1000)
- expiresIn -= self.threshold
- if (expiresIn > self.threshold) {
- return tokenDecoded
- }
- }
- // getting new token
tokens = await self.authenticateFn()
- tokenDecoded = decodeToken(tokens.access_token)
- logger.debug({
- component: 'auth',
- message: `received token response`,
- tokens: tokens,
- tokenDecoded: tokenDecoded
- })
- return tokenDecoded
}
catch (e) {
if (e.response) {
logResponse(e.response)
+ Alarm.noToken(true)
+ }
+ else {
+ Alarm.authOffline(true)
}
throw e
}
+ tokenDecoded = decodeToken(tokens.access_token)
+ logger.debug({
+ component: 'auth',
+ message: `received token response`,
+ tokens,
+ tokenDecoded
+ })
+ return tokenDecoded
}
/**
diff --git a/lib/scan.js b/lib/scan.js
index bde0814..8bf38ea 100644
--- a/lib/scan.js
+++ b/lib/scan.js
@@ -5,10 +5,12 @@ import { serializeError } from 'serialize-error'
import fg from 'fast-glob'
import lineByLine from 'n-readlines'
import fs from 'node:fs'
+import Alarm from './alarm.js'
const component = 'scan'
const historySet = new Set() // in memory history set
let isWriteScheduled = false // flag to indicate if there is pending files to write to the history file
+let timeoutId // id of the active setTimeout
/**
* Utility function that calls initHistory() and startScanner()
@@ -16,6 +18,8 @@ let isWriteScheduled = false // flag to indicate if there is pending files to wr
function initScanner() {
initHistory()
startScanner()
+ Alarm.on('alarmRaised', onAlarmRaised)
+ Alarm.on('alarmLowered', onAlarmLowered)
}
/**
@@ -79,7 +83,7 @@ function removeStaleFiles(currentFilesSet){
* References options properties {path, scanInterval}.
*/
function scheduleNextScan() {
- setTimeout(() => {
+ timeoutId = setTimeout(() => {
startScanner().catch(e => {
logger.error({ component, error: serializeError(e) })
})
@@ -93,6 +97,19 @@ function scheduleNextScan() {
})
}
+/**
+ * Cancels the next scan and logs.
+ * References options properties {path}.
+ */
+function cancelNextScan() {
+ clearTimeout(timeoutId)
+ logger.info({
+ component,
+ message: `scan cancelled`,
+ path: options.path
+ })
+}
+
/**
* Returns immediately if options.historyFile is falsy.
* Initializes the history Set by reading it from a file and adding each line to the history set.
@@ -297,6 +314,39 @@ function isHistoryFileWriteable() {
}
}
+/**
+ * @typedef {import('./alarm.js').AlarmType} AlarmType
+ */
+
+/**
+ * Handles raised alarms
+ * @param {AlarmType} alarmType - The type of alarm.
+ * Intended to be a callback function of Alarm.on('alarmRaised')
+ */
+function onAlarmRaised(alarmType) {
+ logger.verbose({
+ component,
+ message: `handling raised alarm`,
+ alarmType
+ })
+ cancelNextScan()
+}
+
+/**
+ * Handles lowered alarms
+ * @param {AlarmType} alarmType - The type of alarm.
+ * Intended to be a callback function of Alarm.on('alarmRaised')
+ */
+function onAlarmLowered(alarmType) {
+ logger.verbose({
+ component,
+ message: `handling lowered alarm`,
+ alarmType
+ })
+ startScanner()
+}
+
+
export {
startScanner,
initHistory,
From 41128fbafd253796a22ac45916cfa8108de1e6ce Mon Sep 17 00:00:00 2001
From: csmig
Date: Mon, 11 Mar 2024 10:59:29 -0400
Subject: [PATCH 04/13] squashed merge of main
---
README.md | 4 ++--
package.json | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index d8126d0..3f7fd00 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
STIG Manager Watcher
-
+
A [STIG Manager](https://github.com/nuwcdivnpt/stig-manager) CLI client that watches a path for test result files formatted as CKL or XCCDF and posts the results to a Collection.
@@ -28,7 +28,7 @@ C:/> stigman-watcher-win.exe [options]
```
### Install globally via NPM and run the module
```
-$ npm install --global stigman-watcher
+$ npm install --global @nuwcdivnpt/stigman-watcher
$ stigman-watcher [options]
```
diff --git a/package.json b/package.json
index 2efc2e2..c7ac8a5 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
{
- "name": "stigman-watcher",
+ "name": "@nuwcdivnpt/stigman-watcher",
"version": "1.4.2",
"description": "CLI that watches a path for STIG test result files on behalf of a STIG Manager Collection.",
"main": "index.js",
@@ -7,7 +7,7 @@
"license": "MIT",
"repository": {
"type": "git",
- "url": "git+https://github.com/nuwcdivnpt/stigman-watcher.git"
+ "url": "https://github.com/NUWCDIVNPT/stigman-watcher.git"
},
"bin": {
"stigman-watcher": "index.js"
From f55e3fe31727930deb6baccdb739fff6a4ca6603 Mon Sep 17 00:00:00 2001
From: csmig
Date: Mon, 18 Mar 2024 06:48:37 -0400
Subject: [PATCH 05/13] retry handlers; shutdown event
---
index.js | 29 +++++++++++++++++++++++++---
lib/alarm.js | 22 +++++++++++++++++++++-
lib/api.js | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--
lib/auth.js | 48 ++++++++++++++++++++++++++++++++++++++++++++++-
lib/consts.js | 6 ++++++
lib/scan.js | 5 +++--
6 files changed, 153 insertions(+), 9 deletions(-)
create mode 100644 lib/consts.js
diff --git a/index.js b/index.js
index 8e3527c..6127dff 100755
--- a/index.js
+++ b/index.js
@@ -7,12 +7,13 @@ if (!configValid) {
process.exit(1)
}
import startFsEventWatcher from './lib/events.js'
-import { getOpenIDConfiguration, getToken } from './lib/auth.js'
+import * as auth from './lib/auth.js'
import * as api from './lib/api.js'
import { serializeError } from 'serialize-error'
import { initScanner } from './lib/scan.js'
import semverGte from 'semver/functions/gte.js'
import Alarm from './lib/alarm.js'
+import * as CONSTANTS from './lib/consts.js'
const minApiVersion = '1.2.7'
@@ -24,6 +25,14 @@ process.on('SIGINT', () => {
process.exit(0)
})
+Alarm.on('shutdown', (exitCode) => {
+ logger.info({
+ component: 'main',
+ message: `received shutdown event with code ${exitCode}, exiting`
+ })
+ process.exit(exitCode)
+})
+
Alarm.on('alarmRaised', (alarmType) => {
logger.error({
component: 'main',
@@ -50,6 +59,7 @@ async function run() {
})
await preflightServices()
+ setupAlarmHandlers()
if (options.mode === 'events') {
startFsEventWatcher()
}
@@ -60,9 +70,22 @@ async function run() {
catch (e) {
logError(e)
logger.end()
+ process.exitCode = CONSTANTS.ERR_FAILINIT
}
}
+function setupAlarmHandlers() {
+ const alarmHandlers = {
+ apiOffline: api.offlineRetryHandler,
+ authOffline: auth.offlineRetryHandler,
+ noGrant: () => Alarm.shutdown(CONSTANTS.ERR_NOGRANT),
+ noToken: () => Alarm.shutdown(CONSTANTS.ERR_NOTOKEN)
+ }
+ Alarm.on('alarmRaised', (alarmType) => {
+ alarmHandlers[alarmType]?.()
+ })
+}
+
function logError(e) {
const errorObj = {
component: e.component || 'main',
@@ -100,8 +123,8 @@ async function hasMinApiVersion () {
async function preflightServices () {
await hasMinApiVersion()
- await getOpenIDConfiguration()
- await getToken()
+ await auth.getOpenIDConfiguration()
+ await auth.getToken()
logger.info({ component: 'main', message: `preflight token request suceeded`})
const promises = [
api.getCollection(options.collectionId),
diff --git a/lib/alarm.js b/lib/alarm.js
index b1599fe..55260fa 100644
--- a/lib/alarm.js
+++ b/lib/alarm.js
@@ -33,6 +33,10 @@ class Alarm extends EventEmitter {
* @param {boolean} state
*/
#emitAlarmEvent (alarmType, state) {
+ if (alarmType === 'shutdown') {
+ this.emit('shutdown', state)
+ return
+ }
if (state) {
this.emit('alarmRaised', alarmType)
}
@@ -42,41 +46,57 @@ class Alarm extends EventEmitter {
}
/**
- * Sets the state of the apiOffline alarm
+ * Sets the state of the apiOffline alarm
+ * and emits an alarmRaised or alarmLowered event
* @param {boolean} state
*/
apiOffline (state) {
+ if (this.#alarms.apiOffline === state) return
this.#alarms.apiOffline = state
this.#emitAlarmEvent( 'apiOffline', state)
}
/**
* Sets the state of the authOffline alarm
+ * and emits an alarmRaised or alarmLowered event
* @param {boolean} state
*/
authOffline (state) {
+ if (this.#alarms.authOffline === state) return
this.#alarms.authOffline = state
this.#emitAlarmEvent( 'authOffline', state)
}
/**
* Sets the state of the noToken alarm
+ * and emits an alarmRaised or alarmLowered event
* @param {boolean} state
*/
noToken (state) {
+ if (this.#alarms.noToken === state) return
this.#alarms.noToken = state
this.#emitAlarmEvent( 'noToken', state)
}
/**
* Sets the state of the noGrant alarm
+ * and emits an alarmRaised or alarmLowered event
* @param {boolean} state
*/
noGrant (state) {
+ if (this.#alarms.noGrant === state) return
this.#alarms.noGrant = state
this.#emitAlarmEvent( 'noGrant', state)
}
+ /**
+ * Emits a shutdown event with the provied exitCode
+ * @param {number} exitCode
+ */
+ shutdown (exitCode) {
+ this.#emitAlarmEvent('shutdown', exitCode)
+ }
+
/** @type {Alarms} */
get alarms() {
return this.#alarms
diff --git a/lib/api.js b/lib/api.js
index 7754a4c..6e02a8a 100644
--- a/lib/api.js
+++ b/lib/api.js
@@ -3,6 +3,7 @@ import { options } from './args.js'
import { getToken, tokens } from './auth.js'
import { logger, getSymbol } from './logger.js'
import Alarm from './alarm.js'
+import * as CONSTANTS from './consts.js'
const cache = {
collection: null,
@@ -52,7 +53,7 @@ async function apiGet(endpoint, authenticate = true) {
}
throw (e)
}
-}
+}
export async function getScapBenchmarkMap() {
const response = await apiGet('/stigs/scap-maps')
@@ -60,10 +61,11 @@ export async function getScapBenchmarkMap() {
return cache.scapBenchmarkMap
}
-export async function getDefinition(jsonPath) {
+async function getDefinition(jsonPath) {
cache.definition = await apiGet(`/op/definition${jsonPath ? '?jsonpath=' + encodeURIComponent(jsonPath) : ''}`, false)
return cache.definition
}
+export {getDefinition}
export async function getCollection(collectionId) {
cache.collection = await apiGet(`/collections/${collectionId}`)
@@ -196,3 +198,49 @@ function logError (e) {
})
}
+/**
+ * interval between API connectivity tests when in alarm condition
+ * @type {number}
+ */
+const alarmRetryDelay = 5000
+/**
+ * max number of API connectivity tests when in alarm condition
+ * @type {number}
+ */
+const alarmRetryLimit = 5
+
+/**
+ * count of API connectivity tests when in alarm condition
+ * @type {number}
+ */
+let alarmRetryCount = 1
+
+/**
+ * Handler for when 'apiOffline' alarm is raised.
+ * Tests for API connectivity by calling the /op/defintion endpoint
+ * and increments alarmRetryCount until reaching the alarmRetryLimit
+ */
+function offlineRetryHandler() {
+ if (alarmRetryCount >= alarmRetryLimit) {
+ logger.info({
+ conponent: 'api',
+ message: 'API connectivity maximum tries reached, requesting shutdown'
+ })
+ Alarm.shutdown(CONSTANTS.ERR_APIOFFLINE)
+ }
+ logger.info({
+ conponent: 'api',
+ message: 'Testing if API is online'
+ })
+ getDefinition('$.info.version')
+ .then(() => {
+ alarmRetryCount = 1
+ Alarm.apiOffline(false)
+ })
+ .catch(() => {
+ alarmRetryCount++
+ setTimeout(offlineRetryHandler, alarmRetryDelay)
+ })
+}
+export {offlineRetryHandler}
+
diff --git a/lib/auth.js b/lib/auth.js
index 0d5a0f2..373eb97 100644
--- a/lib/auth.js
+++ b/lib/auth.js
@@ -5,6 +5,7 @@ import {options} from './args.js'
import jwt from 'jsonwebtoken'
import { randomBytes } from 'crypto'
import Alarm from './alarm.js'
+import * as CONSTANTS from './consts.js'
const self = {}
@@ -226,4 +227,49 @@ function logResponse (response) {
})
}
-export { getToken, getOpenIDConfiguration, tokens }
+/**
+ * interval between IdP connectivity tests when in alarm condition
+ * @type {number}
+ */
+const alarmRetryDelay = 5000
+/**
+ * max number of IdP connectivity tests when in alarm condition
+ * @type {number}
+ */
+const alarmRetryLimit = 5
+
+/**
+ * count of IdP connectivity tests when in alarm condition
+ * @type {number}
+ */
+let alarmRetryCount = 1
+
+/**
+ * Handler for when 'authiOffline' alarm is raised.
+ * Tests for IdP connectivity by calling the OIDC metadata endpoint
+ * and increments alarmRetryCount until reaching the alarmRetryLimit
+ */
+function offlineRetryHandler() {
+ if (alarmRetryCount >= alarmRetryLimit) {
+ logger.info({
+ conponent: 'auth',
+ message: 'IdP connectivity maximum tries reached, requesting shutdown'
+ })
+ Alarm.shutdown(CONSTANTS.ERR_AUTHOFFLINE)
+ }
+ logger.info({
+ conponent: 'api',
+ message: 'Testing if API is online'
+ })
+ getOpenIDConfiguration()
+ .then(() => {
+ alarmRetryCount = 1
+ Alarm.authOffline(false)
+ })
+ .catch(() => {
+ alarmRetryCount++
+ setTimeout(offlineRetryHandler, alarmRetryDelay)
+ })
+}
+
+export { getToken, getOpenIDConfiguration, offlineRetryHandler, tokens }
diff --git a/lib/consts.js b/lib/consts.js
new file mode 100644
index 0000000..b52d3c9
--- /dev/null
+++ b/lib/consts.js
@@ -0,0 +1,6 @@
+export const ERR_APIOFFLINE = 1
+export const ERR_AUTHOFFLINE = 2
+export const ERR_NOTOKEN = 3
+export const ERR_NOGRANT = 4
+export const ERR_UNKNOWN = 5
+export const ERR_FAILINIT = 6
diff --git a/lib/scan.js b/lib/scan.js
index 8bf38ea..0b96eea 100644
--- a/lib/scan.js
+++ b/lib/scan.js
@@ -148,8 +148,9 @@ function initHistory() {
}
if (isHistoryFileWriteable()) {
- // Handle the interrupt signal
+ // Handle the interrupt signal and shutdown event
process.prependListener('SIGINT', interruptHandler)
+ Alarm.prependListener('shutdown', interruptHandler)
// Set the write interval handler
setInterval(writeIntervalHandler, options.historyWriteInterval)
logger.verbose({
@@ -175,7 +176,7 @@ function initHistory() {
function interruptHandler() {
logger.info({
component,
- message: `received SIGINT, try writing history to file`
+ message: `received SIGINT or shutdown event, try writing history to file`
})
writeHistoryToFile()
}
From f642cb8b64b22d86769a69b91a4f648368995b87 Mon Sep 17 00:00:00 2001
From: csmig
Date: Mon, 18 Mar 2024 14:36:10 -0400
Subject: [PATCH 06/13] wip
---
index.js | 9 ++++++---
lib/alarm.js | 16 ++++++++++++++++
lib/api.js | 29 +++++++++++++++--------------
3 files changed, 37 insertions(+), 17 deletions(-)
diff --git a/index.js b/index.js
index 6127dff..2c63983 100755
--- a/index.js
+++ b/index.js
@@ -26,7 +26,7 @@ process.on('SIGINT', () => {
})
Alarm.on('shutdown', (exitCode) => {
- logger.info({
+ logger.error({
component: 'main',
message: `received shutdown event with code ${exitCode}, exiting`
})
@@ -41,7 +41,7 @@ Alarm.on('alarmRaised', (alarmType) => {
})
Alarm.on('alarmLowered', (alarmType) => {
- logger.error({
+ logger.info({
component: 'main',
message: `Alarm lowered: ${alarmType}`
})
@@ -133,7 +133,7 @@ async function preflightServices () {
api.getScapBenchmarkMap()
]
await Promise.all(promises)
- setInterval(refreshCollection, 10 * 60000)
+ setInterval(refreshCollection, 1 * 60000)
// OAuth scope 'stig-manager:user:read' was not required for early versions of Watcher
// For now, fail gracefully if we are blocked from calling /user
@@ -143,6 +143,7 @@ async function preflightServices () {
}
catch (e) {
logger.warn({ component: 'main', message: `preflight user request failed; token may be missing scope 'stig-manager:user:read'? Watcher will not set {"status": "accepted"}`})
+ Alarm.noGrant(false)
}
logger.info({ component: 'main', message: `prefilght api requests suceeded`})
}
@@ -157,6 +158,7 @@ function getObfuscatedConfig (options) {
async function refreshUser() {
try {
+ if (Alarm.isAlarmed()) return
await api.getUser()
}
catch (e) {
@@ -166,6 +168,7 @@ async function refreshUser() {
async function refreshCollection() {
try {
+ if (Alarm.isAlarmed()) return
await api.getCollection(options.collectionId)
}
catch (e) {
diff --git a/lib/alarm.js b/lib/alarm.js
index 55260fa..46feadc 100644
--- a/lib/alarm.js
+++ b/lib/alarm.js
@@ -89,6 +89,22 @@ class Alarm extends EventEmitter {
this.#emitAlarmEvent( 'noGrant', state)
}
+ /**
+ * Returns an array of the raised alarm types
+ * @returns {string[]}
+ */
+ raisedAlarms () {
+ return Object.keys(this.#alarms).filter(key=>this.#alarms[key])
+ }
+
+ /**
+ * Returns true if any alarm is raised
+ * @returns {boolean}
+ */
+ isAlarmed () {
+ return Object.values(this.#alarms).some(value=>value)
+ }
+
/**
* Emits a shutdown event with the provied exitCode
* @param {number} exitCode
diff --git a/lib/api.js b/lib/api.js
index 6e02a8a..597b3df 100644
--- a/lib/api.js
+++ b/lib/api.js
@@ -13,8 +13,7 @@ const cache = {
scapBenchmarkMap: null,
stigs: null
}
-const _cache = cache
-export { _cache as cache }
+export {cache}
async function apiGet(endpoint, authenticate = true) {
const requestOptions = {
@@ -213,7 +212,7 @@ const alarmRetryLimit = 5
* count of API connectivity tests when in alarm condition
* @type {number}
*/
-let alarmRetryCount = 1
+let alarmRetryCount = 0
/**
* Handler for when 'apiOffline' alarm is raised.
@@ -221,25 +220,27 @@ let alarmRetryCount = 1
* and increments alarmRetryCount until reaching the alarmRetryLimit
*/
function offlineRetryHandler() {
- if (alarmRetryCount >= alarmRetryLimit) {
- logger.info({
- conponent: 'api',
- message: 'API connectivity maximum tries reached, requesting shutdown'
- })
- Alarm.shutdown(CONSTANTS.ERR_APIOFFLINE)
- }
logger.info({
- conponent: 'api',
+ component: 'api',
message: 'Testing if API is online'
})
+ alarmRetryCount++
getDefinition('$.info.version')
.then(() => {
- alarmRetryCount = 1
+ alarmRetryCount = 0
Alarm.apiOffline(false)
})
.catch(() => {
- alarmRetryCount++
- setTimeout(offlineRetryHandler, alarmRetryDelay)
+ if (alarmRetryCount >= alarmRetryLimit) {
+ logger.info({
+ component: 'api',
+ message: 'API connectivity maximum tries reached, requesting shutdown'
+ })
+ Alarm.shutdown(CONSTANTS.ERR_APIOFFLINE)
+ }
+ else {
+ setTimeout(offlineRetryHandler, alarmRetryDelay)
+ }
})
}
export {offlineRetryHandler}
From c8fb06f5f4111c26f09b6d872000b06a445057ca Mon Sep 17 00:00:00 2001
From: csmig
Date: Wed, 20 Mar 2024 19:04:59 -0400
Subject: [PATCH 07/13] nightly
---
index.js | 31 +++++++++-----
lib/api.js | 113 ++++++++++++++++++++------------------------------
lib/auth.js | 18 ++++++--
lib/consts.js | 1 +
4 files changed, 82 insertions(+), 81 deletions(-)
diff --git a/index.js b/index.js
index 2c63983..d204626 100755
--- a/index.js
+++ b/index.js
@@ -2,7 +2,7 @@
import { logger, getSymbol } from './lib/logger.js'
import { options, configValid } from './lib/args.js'
if (!configValid) {
- logger.error({ component: 'main', message: 'invalid configuration... Exiting'})
+ logger.error({ component, message: 'invalid configuration... Exiting'})
logger.end()
process.exit(1)
}
@@ -16,10 +16,11 @@ import Alarm from './lib/alarm.js'
import * as CONSTANTS from './lib/consts.js'
const minApiVersion = '1.2.7'
+const component = 'index'
process.on('SIGINT', () => {
logger.info({
- component: 'main',
+ component,
message: 'received SIGINT, exiting'
})
process.exit(0)
@@ -27,7 +28,7 @@ process.on('SIGINT', () => {
Alarm.on('shutdown', (exitCode) => {
logger.error({
- component: 'main',
+ component,
message: `received shutdown event with code ${exitCode}, exiting`
})
process.exit(exitCode)
@@ -35,14 +36,14 @@ Alarm.on('shutdown', (exitCode) => {
Alarm.on('alarmRaised', (alarmType) => {
logger.error({
- component: 'main',
+ component,
message: `Alarm raised: ${alarmType}`
})
})
Alarm.on('alarmLowered', (alarmType) => {
logger.info({
- component: 'main',
+ component,
message: `Alarm lowered: ${alarmType}`
})
})
@@ -52,7 +53,7 @@ await run()
async function run() {
try {
logger.info({
- component: 'main',
+ component,
message: 'running',
pid: process.pid,
options: getObfuscatedConfig(options)
@@ -88,7 +89,7 @@ function setupAlarmHandlers() {
function logError(e) {
const errorObj = {
- component: e.component || 'main',
+ component: e.component || 'index',
message: e.message,
}
if (e.request) {
@@ -112,7 +113,7 @@ function logError(e) {
async function hasMinApiVersion () {
const [remoteApiVersion] = await api.getDefinition('$.info.version')
- logger.info({ component: 'main', message: `preflight API version`, minApiVersion, remoteApiVersion})
+ logger.info({ component, message: `preflight API version`, minApiVersion, remoteApiVersion})
if (semverGte(remoteApiVersion, minApiVersion)) {
return true
}
@@ -125,7 +126,7 @@ async function preflightServices () {
await hasMinApiVersion()
await auth.getOpenIDConfiguration()
await auth.getToken()
- logger.info({ component: 'main', message: `preflight token request suceeded`})
+ logger.info({ component, message: `preflight token request suceeded`})
const promises = [
api.getCollection(options.collectionId),
api.getCollectionAssets(options.collectionId),
@@ -142,10 +143,10 @@ async function preflightServices () {
setInterval(refreshUser, 10 * 60000)
}
catch (e) {
- logger.warn({ component: 'main', message: `preflight user request failed; token may be missing scope 'stig-manager:user:read'? Watcher will not set {"status": "accepted"}`})
+ logger.warn({ component, message: `preflight user request failed; token may be missing scope 'stig-manager:user:read'? Watcher will not set {"status": "accepted"}`})
Alarm.noGrant(false)
}
- logger.info({ component: 'main', message: `prefilght api requests suceeded`})
+ logger.info({ component, message: `prefilght api requests suceeded`})
}
function getObfuscatedConfig (options) {
@@ -159,6 +160,10 @@ function getObfuscatedConfig (options) {
async function refreshUser() {
try {
if (Alarm.isAlarmed()) return
+ logger.info({
+ component,
+ message: 'refreshing user cache'
+ })
await api.getUser()
}
catch (e) {
@@ -169,6 +174,10 @@ async function refreshUser() {
async function refreshCollection() {
try {
if (Alarm.isAlarmed()) return
+ logger.info({
+ component,
+ message: 'refreshing collection cache'
+ })
await api.getCollection(options.collectionId)
}
catch (e) {
diff --git a/lib/api.js b/lib/api.js
index 597b3df..b01c08c 100644
--- a/lib/api.js
+++ b/lib/api.js
@@ -14,14 +14,16 @@ const cache = {
stigs: null
}
export {cache}
-
-async function apiGet(endpoint, authenticate = true) {
+async function apiRequest({method = 'GET', endpoint, json, authenticate = true, fullResponse = false}) {
const requestOptions = {
+ method,
+ url: `${options.api}${endpoint}`,
responseType: 'json',
timeout: {
- request: 5000
+ request: CONSTANTS.REQUEST_TIMEOUT
}
}
+
if (authenticate) {
try {
await getToken()
@@ -35,12 +37,20 @@ async function apiGet(endpoint, authenticate = true) {
Authorization: `Bearer ${tokens.access_token}`
}
}
+
+ if (json) requestOptions.json = json
+
try {
- const response = await got.get(`${options.api}${endpoint}`, requestOptions)
+ const response = await got(requestOptions)
logResponse (response )
- return response.body
+ return fullResponse ? response : response.body
}
catch (e) {
+ // accept a client error for POST /assets if it reports a duplicate name
+ if (e.response?.statusCode === 400 && e.response?.body?.message === 'Duplicate name') {
+ logResponse(e.response)
+ return fullResponse ? e?.response : e?.response?.body
+ }
e.component = 'api'
logError(e)
// grant problem
@@ -55,95 +65,64 @@ async function apiGet(endpoint, authenticate = true) {
}
export async function getScapBenchmarkMap() {
- const response = await apiGet('/stigs/scap-maps')
- cache.scapBenchmarkMap = new Map(response.map(apiScapMap => [apiScapMap.scapBenchmarkId, apiScapMap.benchmarkId]))
+ const body = await apiRequest({endpoint: '/stigs/scap-maps'})
+ cache.scapBenchmarkMap = new Map(body.map(apiScapMap => [apiScapMap.scapBenchmarkId, apiScapMap.benchmarkId]))
return cache.scapBenchmarkMap
}
async function getDefinition(jsonPath) {
- cache.definition = await apiGet(`/op/definition${jsonPath ? '?jsonpath=' + encodeURIComponent(jsonPath) : ''}`, false)
+ cache.definition = await apiRequest({
+ endpoint: `/op/definition${jsonPath ? '?jsonpath=' + encodeURIComponent(jsonPath) : ''}`,
+ authenticate: false
+ })
return cache.definition
}
export {getDefinition}
export async function getCollection(collectionId) {
- cache.collection = await apiGet(`/collections/${collectionId}`)
+ cache.collection = await apiRequest({endpoint: `/collections/${collectionId}`})
return cache.collection
}
export async function getCollectionAssets(collectionId) {
- cache.assets = await apiGet(`/assets?collectionId=${collectionId}&projection=stigs`)
+ cache.assets = await apiRequest({endpoint: `/assets?collectionId=${collectionId}&projection=stigs`})
return cache.assets
}
export async function getInstalledStigs() {
- cache.stigs = await apiGet('/stigs')
+ cache.stigs = await apiRequest({endpoint: '/stigs'})
return cache.stigs
}
export async function createOrGetAsset(asset) {
- try {
- await getToken()
- const response = await got.post(`${options.api}/assets?projection=stigs`, {
- headers: {
- Authorization: `Bearer ${tokens.access_token}`
- },
- json: asset,
- responseType: 'json'
- })
- logResponse(response)
- return { created: true, apiAsset: response.body }
- }
- catch (e) {
- if (e.response.statusCode === 400 && e.response.body.message === 'Duplicate name') {
- logResponse(e.response)
- return { created: false, apiAsset: e.response.body.data }
- }
- e.component = 'api'
- throw (e)
- }
+ const response = await apiRequest({
+ method: 'POST',
+ endpoint: '/assets?projection=stigs',
+ json: asset,
+ fullResponse: true
+ })
+ const created = response.statusCode === 201
+ return { created, apiAsset: response.body }
}
-export async function patchAsset(assetId, body) {
- try {
- await getToken()
- const response = await got.patch(`${options.api}/assets/${assetId}?projection=stigs`, {
- headers: {
- Authorization: `Bearer ${tokens.access_token}`
- },
- json: body,
- responseType: 'json'
- })
- logResponse(response)
- return response.body
- }
- catch (e) {
- e.component = 'api'
- throw (e)
- }
+export function patchAsset(assetId, body) {
+ return apiRequest({
+ method: 'PATCH',
+ endpoint: `/assets/${assetId}?projection=stigs`,
+ json: body
+ })
}
-export async function postReviews(collectionId, assetId, reviews) {
- try {
- await getToken()
- const response = await got.post(`${options.api}/collections/${collectionId}/reviews/${assetId}`, {
- headers: {
- Authorization: `Bearer ${tokens.access_token}`
- },
- json: reviews,
- responseType: 'json'
- })
- logResponse(response)
- return response.body
- }
- catch (e) {
- e.component = 'api'
- throw (e)
- }
+export function postReviews(collectionId, assetId, reviews) {
+ return apiRequest({
+ method: 'POST',
+ endpoint: `/collections/${collectionId}/reviews/${assetId}`,
+ json: reviews
+ })
}
export async function getUser() {
- cache.user = await apiGet('/user')
+ cache.user = await apiRequest({endpoint: '/user'})
return cache.user
}
@@ -185,7 +164,7 @@ function logResponse (response) {
function logError (e) {
logger.error({
component: 'api',
- message: 'query error',
+ message: e.message,
request: {
method: e.request?.options?.method,
url: e.request?.requestUrl
diff --git a/lib/auth.js b/lib/auth.js
index 373eb97..fd58e9a 100644
--- a/lib/auth.js
+++ b/lib/auth.js
@@ -34,9 +34,15 @@ async function getOpenIDConfiguration () {
url: wellKnownUrl
}
})
+ const requestOptions = {
+ responseType: 'json',
+ timeout: {
+ request: CONSTANTS.REQUEST_TIMEOUT
+ }
+ }
let response
try {
- response = await got.get(wellKnownUrl, { responseType: 'json' })
+ response = await got.get(wellKnownUrl, requestOptions)
}
catch (e) {
if (e.response) {
@@ -100,7 +106,10 @@ async function authenticateClientSecret () {
username: options.clientId,
password: options.clientSecret,
scope: self.scope,
- responseType: 'json'
+ responseType: 'json',
+ timeout: {
+ request: CONSTANTS.REQUEST_TIMEOUT
+ }
}
logger.debug({
@@ -155,7 +164,10 @@ async function authenticateSignedJwt () {
client_assertion: signedJwt,
scope: self.scope
},
- responseType: 'json'
+ responseType: 'json',
+ timeout: {
+ request: CONSTANTS.REQUEST_TIMEOUT
+ }
}
logger.debug({
message: 'sending signed JWT authentication request',
diff --git a/lib/consts.js b/lib/consts.js
index b52d3c9..a584ca2 100644
--- a/lib/consts.js
+++ b/lib/consts.js
@@ -4,3 +4,4 @@ export const ERR_NOTOKEN = 3
export const ERR_NOGRANT = 4
export const ERR_UNKNOWN = 5
export const ERR_FAILINIT = 6
+export const REQUEST_TIMEOUT = 5000
From b189da1b3337b761601b2031bb6ea886cfb8837e Mon Sep 17 00:00:00 2001
From: csmig
Date: Sat, 23 Mar 2024 09:13:43 -0400
Subject: [PATCH 08/13] refactor api.js
---
index.js | 2 +-
lib/api.js | 24 +++++++++++++++++++-----
lib/auth.js | 35 ++++++++++++++++++-----------------
3 files changed, 38 insertions(+), 23 deletions(-)
diff --git a/index.js b/index.js
index d204626..f508bb4 100755
--- a/index.js
+++ b/index.js
@@ -134,7 +134,7 @@ async function preflightServices () {
api.getScapBenchmarkMap()
]
await Promise.all(promises)
- setInterval(refreshCollection, 1 * 60000)
+ setInterval(refreshCollection, 1 * 60000) // todo: change back to 10
// OAuth scope 'stig-manager:user:read' was not required for early versions of Watcher
// For now, fail gracefully if we are blocked from calling /user
diff --git a/lib/api.js b/lib/api.js
index b01c08c..f663bdc 100644
--- a/lib/api.js
+++ b/lib/api.js
@@ -14,7 +14,21 @@ const cache = {
stigs: null
}
export {cache}
-async function apiRequest({method = 'GET', endpoint, json, authenticate = true, fullResponse = false}) {
+
+/**
+ * Sends requests to the STIG Manager API and returns the response
+ * @async
+ * @function apiRequest
+ * @param {Object} options
+ * @property {'GET'|'POST'|'PATCH'} [options.method='GET'] optional, HTTP method
+ * @property {string} options.endpoint required, API endpoint
+ * @property {Object=} options.json optional, object to be stringified into request body
+ * @property {boolean} [options.authorize=true] optional, whether the request should be authorized with a JWT
+ * @property {boolean} [options.fullResponse=false] optional, whether to return the response body or the got response object
+ * @returns {Promise