diff --git a/.eslintrc.js b/.eslintrc.js index 3b4488bdb1..2e3218d37f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -49,6 +49,7 @@ module.exports = { "rules": { "max-len": ["warn", 150], "no-console": "error", + "no-extra-parens": "error", "no-multiple-empty-lines": "warn", "no-trailing-spaces": "warn", "@typescript-eslint/ban-types": "off", diff --git a/.github/updateReleaseMarkdown.js b/.github/updateReleaseMarkdown.js new file mode 100644 index 0000000000..56406f6c0c --- /dev/null +++ b/.github/updateReleaseMarkdown.js @@ -0,0 +1,65 @@ +const fs = require('fs'); +const path = require('path'); + +const mdFilePath = path.join(__dirname, '../RELEASE_HISTORY.md'); + +// Build the new row to be added +const newRow = `| v${process.env.NEW_VERSION} | ${new Date().toISOString().split('T')[0].slice(0, 7)} | **Active** | [Release Notes](https://docs.zowe.org/stable/whats-new/release-notes/v${process.env.NEW_VERSION.replace(/\./g, '_')}) |`; + +// Read, Update and Write to Markdown File +function updateReleaseHistory(newRow) { + fs.readFile(mdFilePath, 'utf8', (err, data) => { + if (err) { + console.error('Error reading the file:', err); + return; + } + + // Find the table and insert the new row after the second row + const lines = data.split('\n'); + let tableLineCount = 0; + for (let i = 0; i < lines.length; i++) { + if (lines[i].startsWith('|') && lines[i].endsWith('|')) { + tableLineCount++; + if (tableLineCount === 2) { + // Insert the new row after the second row + lines.splice(i + 1, 0, newRow); + break; + } + } + } + + fs.writeFile(mdFilePath, lines.join('\n'), 'utf8', (err) => { + if (err) { + console.error('Error writing the file:', err); + return; + } + console.log('Markdown file updated successfully.'); + }); + }); +} + +// Update the zoweVersion in package.json +function updatePackageJsonVersion(newVersion) { + const packageJsonPath = path.join(__dirname, '../packages/cli/package.json'); + fs.readFile(packageJsonPath, 'utf8', (err, data) => { + if (err) { + console.error('Error reading package.json:', err); + return; + } + + let packageJson = JSON.parse(data); + packageJson.zoweVersion = `v${newVersion}`; + + fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf8', (err) => { + if (err) { + console.error('Error writing to package.json:', err); + return; + } + console.log('package.json updated successfully.'); + }); + }); +} + +// Execute the functions +updatePackageJsonVersion(process.env.NEW_VERSION); +updateReleaseHistory(newRow); \ No newline at end of file diff --git a/.github/updateReleaseMarkdown_BROKEN.js b/.github/updateReleaseMarkdown_BROKEN.js new file mode 100644 index 0000000000..a8d3d1b674 --- /dev/null +++ b/.github/updateReleaseMarkdown_BROKEN.js @@ -0,0 +1,111 @@ +const fs = require('fs'); +const path = require('path'); +const https = require('https'); + +// This script is attempting to add whatever list of the CLI team is shown in the TSC repo https://raw.githubusercontent.com/zowe/community/master/COMMITTERS.md. +// Despite efforts, this is not working. Adam will always be cut off (possibly just whoever is first in the table). +// Leaving this code present and hoping that the problem with this file can be solved in the future. + +// URL of the raw markdown file to be appended to RELEASE_HISTORY.md +const url = 'https://raw.githubusercontent.com/zowe/community/master/COMMITTERS.md'; + +// Build the new row to be added +const newVersion = process.env.NEW_VERSION; +const newRow = `| v${newVersion} | ${new Date().toISOString().split('T')[0].slice(0, 7)} | **Active** | [Release Notes](https://docs.zowe.org/stable/whats-new/release-notes/v${newVersion.replace(/\./g, '_')}) |`; + +const mdFilePath = path.join(__dirname, '../RELEASE_HISTORY.md'); + +// Function to fetch CLI team from a URL +function fetchCliTeam(url) { + return new Promise((resolve, reject) => { + https.get(url, (res) => { + let data = ''; + + // A chunk of data has been received + res.on('data', (chunk) => { + data += chunk; + }); + + // The whole response has been received + res.on('end', () => { + // Extract only the CLI contributors section + const cliSectionMatch = data.match(/### Zowe CLI Squad[\s\S]*?(?=###|$)/); + const cliSection = cliSectionMatch ? cliSectionMatch[0] : ''; + resolve(cliSection); + }); + }).on('error', (err) => { + reject(err); + }); + }); +} + +// Function to remove existing CLI team section and append new one +function updateCliTeamInMd(cliTeam) { + // Read the current content of the markdown file + fs.readFile(mdFilePath, 'utf8', (err, data) => { + if (err) { + console.error('Error reading the file:', err); + return; + } + + // Remove the old CLI squad section and replace it with the new one + const updatedData = data.replace(/### Zowe CLI Squad[\s\S]*?(?=###|$)/, cliTeam + '\n'); + + // Write the updated data back to the file + fs.writeFile(mdFilePath, updatedData, 'utf8', (err) => { + if (err) { + console.error('Error writing the file:', err); + return; + } + console.log('CLI team has been updated in RELEASE_HISTORY.md successfully.'); + }); + }); +} + +// Main function to fetch CLI team and update RELEASE_HISTORY +async function appendCliTeam() { + try { + const cliTeam = await fetchCliTeam(url); + updateCliTeamInMd(cliTeam); + } catch (error) { + console.error('Error fetching CLI team:', error); + } +} + +// Read, Update and Write to Markdown File +function updateReleaseHistory(newRow) { + fs.readFile(mdFilePath, 'utf8', (err, data) => { + if (err) { + console.error('Error reading the file:', err); + return; + } + + // Find the table and insert the new row after the second row + const lines = data.split('\n'); + let tableLineCount = 0; + for (let i = 0; i < lines.length; i++) { + if (lines[i].startsWith('|') && lines[i].endsWith('|')) { + tableLineCount++; + if (tableLineCount === 2) { + // Insert the new row after the second row + lines.splice(i + 1, 0, newRow); + break; + } + } + } + + fs.writeFile(mdFilePath, lines.join('\n'), 'utf8', (err) => { + if (err) { + console.error('Error writing the file:', err); + return; + } + console.log('Markdown file updated successfully.'); + }); + }); +} + +// Execute the two main functions +(async () => { + await appendCliTeam(); + updateReleaseHistory(newRow); +})(); \ No newline at end of file diff --git a/.github/workflows/secrets-sdk.yml b/.github/workflows/secrets-sdk.yml index f1c94da3cf..7f59ab1125 100644 --- a/.github/workflows/secrets-sdk.yml +++ b/.github/workflows/secrets-sdk.yml @@ -29,10 +29,9 @@ jobs: settings: - host: macos-latest target: x86_64-apple-darwin - build: | - npm run build + build: npm run build -- --target x86_64-apple-darwin - host: windows-latest - build: npm run build + build: npm run build -- --target x86_64-pc-windows-msvc target: x86_64-pc-windows-msvc - host: windows-latest build: | @@ -67,13 +66,7 @@ jobs: CARGO=cross npm run build -- --target x86_64-unknown-linux-musl - host: macos-latest target: aarch64-apple-darwin - build: | - sudo rm -Rf /Library/Developer/CommandLineTools/SDKs/*; - export CC=$(xcrun -f clang); - export CXX=$(xcrun -f clang++); - SYSROOT=$(xcrun --sdk macosx --show-sdk-path); - export CFLAGS="-isysroot $SYSROOT -isystem $SYSROOT"; - npm run build -- --target aarch64-apple-darwin + build: npm run build -- --target aarch64-apple-darwin - host: ubuntu-latest target: aarch64-unknown-linux-gnu use-cross: true @@ -210,8 +203,11 @@ jobs: settings: - host: windows-latest target: x86_64-pc-windows-msvc + - host: macos-latest + target: aarch64-apple-darwin - host: macos-latest target: x86_64-apple-darwin + architecture: x64 - host: ubuntu-latest target: x86_64-unknown-linux-gnu - host: ubuntu-latest @@ -237,6 +233,7 @@ jobs: node-version: ${{ matrix.node }} check-latest: true cache: npm + architecture: ${{ matrix.settings.architecture }} - name: Install dependencies run: npm ci --ignore-scripts - name: Download artifacts diff --git a/.github/workflows/zoweReleaseVersion.yaml b/.github/workflows/zoweReleaseVersion.yaml new file mode 100644 index 0000000000..0ec1e0e2b8 --- /dev/null +++ b/.github/workflows/zoweReleaseVersion.yaml @@ -0,0 +1,74 @@ +name: Update Zowe Version and Create PR + +on: + workflow_dispatch: + inputs: + major_version: + description: 'Major version (default is 3)' + required: true + default: '3' + minor_version: + description: 'Minor version' + required: true + patch_version: + description: 'Patch version' + required: true + +jobs: + update_versions_and_create_pr: + runs-on: ubuntu-latest + + steps: + - name: Checkout CLI Repo + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: lts/* + + - name: Set Variables and Ensure Increase in Semver + id: get_zowe_versions + run: | + current_version=$(jq -r '.zoweVersion' packages/cli/package.json) + current_version="${current_version#v}" # Strip the 'v' prefix + echo "current_version=$current_version" >> $GITHUB_ENV + new_version="${{ github.event.inputs.major_version }}.${{ github.event.inputs.minor_version }}.${{ github.event.inputs.patch_version }}" + echo "new_version=$new_version" >> $GITHUB_ENV + echo "PACKAGE_JSON_PATH=packages/cli/package.json" >> $GITHUB_ENV + if [[ "$new_version" < "$current_version" ]]; then + echo "Error: New version $new_version is not greater than current version $current_version." + exit 1 + fi + + - name: Create Branch + run: | + branch_name="update-version-v${{ env.new_version }}" + echo "branch_name=$branch_name" >> $GITHUB_ENV + git checkout -b "$branch_name" + + - name: Update Zowe Version in cli/package.json + run: | + jq ".zoweVersion = \"v${{ env.new_version }}\"" ${{ env.PACKAGE_JSON_PATH }} > package.tmp.json && mv package.tmp.json ${{ env.PACKAGE_JSON_PATH }} + + - name: Update RELEASE_HISTORY.md + run: node ".github/updateReleaseMarkdown.js" + env: + NEW_VERSION: ${{ env.new_version }} + + - name: Commit and Push Changes + run: | + git config --global user.name "${{ secrets.ZOWE_ROBOT_USER }}" + git config --global user.email "${{ secrets.ZOWE_ROBOT_EMAIL }}" + git add "${{ env.PACKAGE_JSON_PATH }}" + git add "RELEASE_HISTORY.md" + git commit -sm "Update version to ${{ env.new_version }}" + git push origin "$branch_name" + + - name: Create Pull Request + run: | + pr_title="Update CLI version to ${{ env.new_version }}" + base_branch="${{ github.ref_name }}" + gh pr create -t "$pr_title" -b "$base_branch" --head "$branch_name" --body "Updating Zowe CLI version to ${{ env.new_version }}" --reviewer zFernand0,t1m0thyj,awharn,gejohnston,traeok,jace-roell,ATorrise + env: + GH_TOKEN: ${{ secrets.ZOWE_ROBOT_TOKEN }} diff --git a/.gitignore b/.gitignore index 53b8187595..21500acf9a 100644 --- a/.gitignore +++ b/.gitignore @@ -121,4 +121,4 @@ packages/imperative/web-help/dist/css/bundle* packages/imperative/web-help/dist/js/ jest-stare/ -jest.user.config.js \ No newline at end of file +jest.user.config.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b8a88c7a59..17dcf64377 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -125,14 +125,20 @@ Add an entry to changelog.md for any PR that introduces a feature, enhancement, **Each changelog entry must:** - Describe the change and how it impacts end users. - Include a relevant Issue # or Pull Request #. +- Include one of the following prefixes: + - `BugFix` - If a fix was added + - `Enhancement` - If a feature or enhancement was introduced + - For breaking changes (only allowed for PRs merged into the "next" branch): + - `LTS Breaking` - If behavior has changed since the last LTS release + - `Next Breaking` - If behavior has changed since an earlier vNext prerelease The following is an example of the markdown that you should insert into the changelog above the last-released version: ``` ## Recent Changes -- Document your changes here. [Issue# or PR#](link-to-issue-or-pr) -- Document another change here. [Issue# or PR#](link-to-issue-or-pr) +- BugFix: Describe the bug fix here. [Issue# or PR#](link-to-issue-or-pr) +- Enhancement: Describe the enhancement here. [Issue# or PR#](link-to-issue-or-pr) ``` **Tips:** diff --git a/RELEASE_HISTORY.md b/RELEASE_HISTORY.md new file mode 100644 index 0000000000..0b2797c4e5 --- /dev/null +++ b/RELEASE_HISTORY.md @@ -0,0 +1,69 @@ +# Zowe CLI Releases + +Zowe follows a regular release schedule with major versions released every two years and minor versions approximately every six weeks. Full details regarding the Zowe release schedule are available on [zowe.org](https://www.zowe.org/download#timeline) and the Zowe Community [Github](https://github.com/zowe/community/blob/master/Technical-Steering-Committee/release.md). + +## Zowe Release Schedule + +### Zowe v3.x LTS Releases +| Version | Release Date | Status | Release Notes | +|:--------:|:------------:|:----------:|:-------------:| +| v3.0.0-prerelease | 2024-08 | **Under Development** | | + +### Major Release Timeline + +![Zowe Major Releases](https://raw.githubusercontent.com/zowe/zowe.github.io/master/assets/img/major_releases.webp) + +### Version Timeframes + +- **Active**: Each major version remains in this phase for 2 years, receiving regular updates and new features. +- **Maintenance**: Following the Active phase, each major version remains in this phase for an additional 2.5 years, receiving only critical fixes and security patches. +- **Under Development**: The pre-Active phase where the next major version is prepared. This phase varies in length and is not available for general consumption. + +### Guarantees + +- **Critical Defects Fixes**: The community will fix critical defects. The criteria for what constitutes a critical defect can be found [here](https://github.com/zowe/community/blob/master/Technical-Steering-Committee/release.md#active-release). +- **Extender Conformance**: Extenders achieving Zowe conformance for the long-term support version will not need to modify their product to remain functional when Zowe updates are provided within the same major version. + +### Recommendations + +- **Production**: Use **Active** or **Maintenance** releases for production due to the guaranteed stability and the community’s commitment to fixing critical defects. +- **Nightly Builds**: Available for integration testing. Use at your own risk. + +## Zowe Release Process + +### Short Summary + +1. Code Freeze date is hit. +2. Each [squad](https://github.com/zowe/community/blob/master/Technical-Steering-Committee/squads.md) provides a version of the code to integrate into the Release Candidate (RC). +3. RC is built and tested with an automatic test suite. +4. RC is deployed and tested by squads. +5. RC is approved by the TSC vote. +6. Release is published. +7. Documentation is published. +8. Release retrospective is held. + +### Release Numbering + +Releases follow [semantic versioning](https://semver.org/) guidelines (MAJOR.MINOR.PATCH). + +- **MAJOR**: Incompatible API changes. +- **MINOR**: Backwards-compatible functionality additions. +- **PATCH**: Backwards-compatible bug fixes. + +### Release Content + +The following [components of the release](https://github.com/zowe/community/blob/master/Technical-Steering-Committee/release.md#release-content) are managed by the CLI squad: + +- **CLI Component** + - CLI Core + - CLI Plugins +- **Client SDKs** + - Node.js Client SDK + - Python Client SDK + + +## Zowe CLI Squad +- https://github.com/zowe/community/blob/master/COMMITTERS.md#zowe-cli-squad +- https://github.com/orgs/zowe/teams/zowe-cli-administrators +- https://github.com/orgs/zowe/teams/zowe-cli-committers +- https://github.com/orgs/zowe/teams/zowe-cli-contributors \ No newline at end of file diff --git a/__tests__/__integration__/__scripts__/imperative_ssh_create_profile.sh b/__tests__/__integration__/__scripts__/imperative_ssh_create_profile.sh deleted file mode 100755 index 909dbe3793..0000000000 --- a/__tests__/__integration__/__scripts__/imperative_ssh_create_profile.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -e - -echo "================SSH CREATE PROFILE===============" -zowe profiles create ssh $* -if [ $? -gt 0 ] -then - exit $? -fi \ No newline at end of file diff --git a/__tests__/__integration__/__scripts__/imperative_ssh_delete_profile.sh b/__tests__/__integration__/__scripts__/imperative_ssh_delete_profile.sh deleted file mode 100755 index e2af8cdc40..0000000000 --- a/__tests__/__integration__/__scripts__/imperative_ssh_delete_profile.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -e - -echo "================SSH DELETE PROFILE===============" -zowe profiles delete ssh $* -if [ $? -gt 0 ] -then - exit $? -fi \ No newline at end of file diff --git a/__tests__/__integration__/__scripts__/imperative_tso_create_profile.sh b/__tests__/__integration__/__scripts__/imperative_tso_create_profile.sh deleted file mode 100755 index 19d39bf380..0000000000 --- a/__tests__/__integration__/__scripts__/imperative_tso_create_profile.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -e - -echo "================TSO CREATE PROFILE===============" -zowe profiles create tso $* -if [ $? -gt 0 ] -then - exit $? -fi \ No newline at end of file diff --git a/__tests__/__integration__/__scripts__/imperative_tso_delete_profile.sh b/__tests__/__integration__/__scripts__/imperative_tso_delete_profile.sh deleted file mode 100755 index 246b20556a..0000000000 --- a/__tests__/__integration__/__scripts__/imperative_tso_delete_profile.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -e - -echo "================TSO DELETE PROFILE===============" -zowe profiles delete tso $* -if [ $? -gt 0 ] -then - exit $? -fi \ No newline at end of file diff --git a/__tests__/__integration__/__scripts__/imperative_zosmf_create_profile.sh b/__tests__/__integration__/__scripts__/imperative_zosmf_create_profile.sh deleted file mode 100755 index 1fcbf96662..0000000000 --- a/__tests__/__integration__/__scripts__/imperative_zosmf_create_profile.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -e - -echo "================ZOSMF CREATE PROFILE===============" -zowe profiles create zosmf $* -if [ $? -gt 0 ] -then - exit $? -fi \ No newline at end of file diff --git a/__tests__/__integration__/__scripts__/imperative_zosmf_delete_profile.sh b/__tests__/__integration__/__scripts__/imperative_zosmf_delete_profile.sh deleted file mode 100755 index 347b33f57d..0000000000 --- a/__tests__/__integration__/__scripts__/imperative_zosmf_delete_profile.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -e - -echo "================ZOSMF DELETE PROFILE===============" -zowe profiles delete zosmf $* -if [ $? -gt 0 ] -then - exit $? -fi \ No newline at end of file diff --git a/__tests__/__integration__/__snapshots__/imperative.secure.integration.test.ts.snap b/__tests__/__integration__/__snapshots__/imperative.secure.integration.test.ts.snap index e6c77aa3e7..1500ca567e 100644 --- a/__tests__/__integration__/__snapshots__/imperative.secure.integration.test.ts.snap +++ b/__tests__/__integration__/__snapshots__/imperative.secure.integration.test.ts.snap @@ -1,47 +1,115 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Imperative Secure Tests Cli Profile Manager Default Credential Management Generic Failure Scenarios should fail if the Credential Manager is unable to retrieve a password 1`] = ` -"Command Preparation Failed: -Unable to load the secure field \\"username\\" associated with the profile \\"profile-name-changed\\" of type \\"username-password\\". -Error Details: -Unable to load credentials. -Could not find an entry in the credential vault for the following: - Service = example_with_profiles - Account = username-password_profile-name-changed_username +exports[`Imperative Secure Tests Imperative Test CLI Secure Tests imperative-test-cli config import failure scenarios should fail to import if location is not specified 1`] = ` +" +Syntax Error: +Missing Positional Argument: location +Argument Description: File path or URL to import from. + +Example: + + - Import config from local file on disk: -Possible Causes: - This could have been caused by any manual removal of credentials from your vault. + $ imperative-test-cli config import ~/Downloads/zowe.config.json + +Use \\"imperative-test-cli config import --help\\" to view command description, usage, and options. +" +`; -Resolutions: - Recreate the credentials in the vault for the particular service in the vault. - To recreate credentials, issue a 'profiles create' sub-command with the --ow flag. +exports[`Imperative Secure Tests Imperative Test CLI Secure Tests imperative-test-cli config list should list the configuration 1`] = ` +"profiles: + secured: + type: secured + properties: + info: + secure: + (empty array) + project_base: + type: base + properties: + secure: + - secret + global_base: + type: base + properties: + secure: + - secret +defaults: + secured: secured + base: project_base +autoStore: true +" +`; +exports[`Imperative Secure Tests Imperative Test CLI Secure Tests imperative-test-cli config list should list the configuration without showing secure values 1`] = ` +"profiles: + secured: + type: secured + properties: + info: + secure: + (empty array) + project_base: + type: base + properties: + secret: (secure value) + secure: + - secret + global_base: + type: base + properties: + secure: + - secret +defaults: + secured: secured + base: project_base +autoStore: true " `; -exports[`Imperative Secure Tests Cli Profile Manager Default Credential Management Generic Failure Scenarios should fail if the Credential Manager is unable to retrieve a password 2`] = ` -"Your default profile named profile-name of type username-password was successfully deleted. -Because you deleted it, the default profile for type username-password has been cleared. -To set a new default profile, run \\"zowe profiles set-default username-password \\". +exports[`Imperative Secure Tests Imperative Test CLI Secure Tests imperative-test-cli config list should list the defaults configuration property 1`] = ` +"secured: secured +base: project_base " `; -exports[`Imperative Secure Tests Cli Profile Manager Default Credential Management Generic Success Scenarios should update a password 1`] = ` +exports[`Imperative Secure Tests Imperative Test CLI Secure Tests imperative-test-cli config list should list the profiles configuration property 1`] = ` +"secured: + type: secured + properties: + info: + secure: + (empty array) +project_base: + type: base + properties: + secure: + - secret +global_base: + type: base + properties: + secure: + - secret " -Warning: The command 'profiles update username-password-profile' is deprecated. -Recommended replacement: The 'config set' command +`; + +exports[`Imperative Secure Tests Imperative Test CLI Secure Tests imperative-test-cli config list should list the root level property names only 1 1`] = ` +"profiles +defaults +autoStore " `; -exports[`Imperative Secure Tests Cli Profile Manager Default Credential Management Generic Success Scenarios should update a password 2`] = ` -"Your default profile named profile-name of type username-password was successfully deleted. -Because you deleted it, the default profile for type username-password has been cleared. -To set a new default profile, run \\"zowe profiles set-default username-password \\". +exports[`Imperative Secure Tests Imperative Test CLI Secure Tests imperative-test-cli config list should list the root level property names only 2 1`] = ` +"profiles +defaults +autoStore " `; -exports[`Imperative Secure Tests imperative-test-cli config profiles should list profiles 1`] = ` +exports[`Imperative Secure Tests Imperative Test CLI Secure Tests imperative-test-cli config profiles should list profiles 1`] = ` "secured -base +project_base +global_base " `; diff --git a/__tests__/__integration__/imperative.integration.subtest.ts b/__tests__/__integration__/imperative.integration.subtest.ts deleted file mode 100644 index b3d42c0247..0000000000 --- a/__tests__/__integration__/imperative.integration.subtest.ts +++ /dev/null @@ -1,164 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ITestEnvironment, runCliScript } from "../__packages__/cli-test-utils"; -import { TestEnvironment } from "../__src__/environment/TestEnvironment"; -import { ITestPropertiesSchema } from "../__src__/properties/ITestPropertiesSchema"; - -let testEnvironment: ITestEnvironment; - -describe("imperative create profile", () => { - - // Create the unique test environment - beforeAll(async () => { - testEnvironment = await TestEnvironment.setUp({ - testName: "imperative_create_profile", - skipProperties: true - }); - }); - - afterAll(async () => { - await TestEnvironment.cleanUp(testEnvironment); - }); - - describe("create zosmf profile", () => { - - afterEach(async () => { - const opts = ["CreateProfileSystemTest"]; - try { - runCliScript(__dirname + "/__scripts__/imperative_zosmf_delete_profile.sh", testEnvironment, opts); - } catch (err) { /* Do nothing */ } - }); - - it("should successfully create a profile", async () => { - const opts = [ - "CreateProfileSystemTest", - "--host", "FAKEHOST", - "--port", "443", - "--user", "FAKEUSER", - "--password", "FAKEPASS", - "--reject-unauthorized", "false" - ]; - - const response = runCliScript(__dirname + "/__scripts__/imperative_zosmf_create_profile.sh", - testEnvironment, opts - ); - expect(response.stderr.toString()).toContain("deprecated"); - expect(response.status).toBe(0); - expect(response.stdout.toString()).toContain("Profile created successfully!"); - expect(response.stdout.toString()).toContain("FAKEHOST"); - expect(response.stdout.toString()).toContain("443"); - // Two values (user and password) should be stored securely - expect((response.stdout.toString().match(/managed by Zowe CLI/g) || []).length).toBe(2); - }); - - it("should successfully create a profile without username, password, or host", async () => { - const opts = [ - "CreateProfileSystemTest", - "--port", "443", - "--reject-unauthorized", "false" - ]; - - const response = runCliScript(__dirname + "/__scripts__/imperative_zosmf_create_profile.sh", - testEnvironment, opts - ); - expect(response.stderr.toString()).toContain("deprecated"); - expect(response.status).toBe(0); - expect(response.stdout.toString()).toContain("Profile created successfully!"); - expect(response.stdout.toString()).toContain("443"); - }); - }); - - describe("create ssh profile", () => { - - afterEach(async () => { - const opts = ["CreateProfileSystemTest"]; - try { - runCliScript(__dirname + "/__scripts__/imperative_ssh_delete_profile.sh", testEnvironment, opts); - } catch (err) { /* Do nothing */ } - }); - - it("should successfully create a profile", async () => { - const opts = [ - "CreateProfileSystemTest", - "--host", "FAKEHOST", - "--port", "22", - "--user", "FAKEUSER", - "--password", "FAKEPASS" - ]; - - const response = runCliScript(__dirname + "/__scripts__/imperative_ssh_create_profile.sh", - testEnvironment, opts - ); - expect(response.stderr.toString()).toContain("deprecated"); - expect(response.status).toBe(0); - expect(response.stdout.toString()).toContain("Profile created successfully!"); - expect(response.stdout.toString()).toContain("FAKEHOST"); - expect(response.stdout.toString()).toContain("22"); - expect(response.stdout.toString()).not.toContain("FAKEUSER"); - expect(response.stdout.toString()).toContain("user: managed by Zowe CLI"); - expect(response.stdout.toString()).toContain("password: managed by Zowe CLI"); - }); - - it("should successfully create a profile without username, password, or host", async () => { - const opts = [ - "CreateProfileSystemTest", - "--port", "22" - ]; - - const response = runCliScript(__dirname + "/__scripts__/imperative_ssh_create_profile.sh", - testEnvironment, opts - ); - expect(response.stderr.toString()).toContain("deprecated"); - expect(response.status).toBe(0); - expect(response.stdout.toString()).toContain("Profile created successfully!"); - expect(response.stdout.toString()).toContain("22"); - }); - }); - - describe("create tso profile", () => { - - afterEach(async () => { - const opts = ["CreateProfileSystemTest"]; - try { - runCliScript(__dirname + "/__scripts__/imperative_tso_delete_profile.sh", testEnvironment, opts); - } catch (err) { /* Do nothing */ } - }); - - it("should successfully create a profile", async () => { - const opts = [ - "CreateProfileSystemTest", - "--account", "FAKEACCT" - ]; - - const response = runCliScript(__dirname + "/__scripts__/imperative_tso_create_profile.sh", - testEnvironment, opts - ); - expect(response.stderr.toString()).toContain("deprecated"); - expect(response.status).toBe(0); - expect(response.stdout.toString()).toContain("Profile created successfully!"); - }); - - it("should successfully create a profile without username, password, or host", async () => { - const opts = [ - "CreateProfileSystemTest" - ]; - - const response = runCliScript(__dirname + "/__scripts__/imperative_tso_create_profile.sh", - testEnvironment, opts - ); - expect(response.stderr.toString()).toContain("deprecated"); - expect(response.status).toBe(0); - expect(response.stdout.toString()).toContain("Profile created successfully!"); - expect(response.stdout.toString()).not.toContain("FAKEACCT"); - }); - }); -}); diff --git a/__tests__/__integration__/imperative.secure.integration.test.ts b/__tests__/__integration__/imperative.secure.integration.test.ts index 1dfb3f02a1..7091c85c7b 100644 --- a/__tests__/__integration__/imperative.secure.integration.test.ts +++ b/__tests__/__integration__/imperative.secure.integration.test.ts @@ -11,21 +11,12 @@ // These tests require access to the same values on the keyring, therefore they cannot run in parallel // The test order is important - some tests depend on other tests not running first - do not change it +// All tests that mess with the keyring must go here - the MacOS Keyring is NOT thread safe, and cannot run anything in parallel /* eslint-disable max-len */ describe("Imperative Secure Tests", () => { - require("./imperative.integration.subtest"); - require("./../../packages/imperative/__tests__/src/packages/profiles/__integration__/CliProfileManager.credentials.integration.subtest"); + require("./../../packages/imperative/__tests__/src/packages/imperative/__integration__/ConfigLoading.integration.subtest"); require("./../../packages/imperative/__tests__/src/packages/imperative/__integration__/PluginManagementFacility.integration.subtest"); - require("./../../packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/init/cli.imperative-test-cli.config.init.integration.subtest"); - require("./../../packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/auto-init/imperative.test.cli.config.auto-init.fruit.integration.subtest"); - require("./../../packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/cli.imperative-test-cli.config.convert-profiles.integration.subtest"); - require("./../../packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/profiles/cli.imperative-test-cli.config.profiles.integration.subtest"); - require("./../../packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/secure/cli.imperative-test-cli.config.secure.integration.subtest"); - require("./../../packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/set/cli.imperative-test-cli.config.set.integration.subtest"); - require("./../../packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/profiles/cli.imperative-test-cli.profiles.create.secured-profile.integration.subtest"); - require("./../../packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/test/cli.imperative-test-cli.test.config-auto-store.integration.subtest"); - require("./../../packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/test/cli.imperative-test-cli.test.config-override.integration.subtest"); + require("../../packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/cli.imperative-test-cli.integration.subtest"); + require("../../packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/Cmd.cli.auth.fruit.integration.subtest"); }); - - diff --git a/__tests__/__packages__/cli-test-utils/CHANGELOG.md b/__tests__/__packages__/cli-test-utils/CHANGELOG.md index 0ec6f57a65..13f5a5fdee 100644 --- a/__tests__/__packages__/cli-test-utils/CHANGELOG.md +++ b/__tests__/__packages__/cli-test-utils/CHANGELOG.md @@ -2,6 +2,34 @@ All notable changes to the Zowe CLI test utils package will be documented in this file. +## Recent Changes + +- Update: Final prerelease + +## `8.0.0-next.202408271330` + +- BugFix: Removed obsolete V1 `profiles` property from the parameters object returned by `mockHandlerParameters` method. + +## `8.0.0-next.202408131445` + +- Update: See `7.28.3` for details + +## `8.0.0-next.202407262216` + +- Update: See `7.28.2` for details + +## `8.0.0-next.202407021516` + +- BugFix: Updated dependencies for technical currency [#2188](https://github.com/zowe/zowe-cli/pull/2188) + +## `8.0.0-next.202402261705` + +- BugFix: Updated dependencies for technical currency. [#2061](https://github.com/zowe/zowe-cli/pull/2061) + +## `8.0.0-next.202311132045` + +- Major: First major version bump for V3 + ## `7.28.3` - BugFix: Refactored code to reduce the use of deprecated functions to prepare for upcoming Node.js 22 support. [#2191](https://github.com/zowe/zowe-cli/issues/2191) diff --git a/__tests__/__packages__/cli-test-utils/package.json b/__tests__/__packages__/cli-test-utils/package.json index 8f594a7738..9572afc711 100644 --- a/__tests__/__packages__/cli-test-utils/package.json +++ b/__tests__/__packages__/cli-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli-test-utils", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "description": "Test utilities package for Zowe CLI plug-ins", "author": "Zowe", "license": "EPL-2.0", @@ -37,15 +37,15 @@ "dependencies": { "find-up": "^5.0.0", "js-yaml": "^4.0.0", - "rimraf": "^3.0.2", - "uuid": "^8.3.2" + "rimraf": "^5.0.0", + "uuid": "^10.0.0" }, "devDependencies": { - "@types/js-yaml": "^4.0.0", - "@types/uuid": "^8.3.0", - "@zowe/imperative": "5.27.1" + "@types/js-yaml": "^4.0.9", + "@types/uuid": "^10.0.0", + "@zowe/imperative": "8.0.0-next.202409111528" }, "peerDependencies": { - "@zowe/imperative": "^5.0.0" + "@zowe/imperative": "^8.0.0-next" } } diff --git a/__tests__/__packages__/cli-test-utils/src/TestUtils.ts b/__tests__/__packages__/cli-test-utils/src/TestUtils.ts index 5b0c702ff6..6952abcc7c 100644 --- a/__tests__/__packages__/cli-test-utils/src/TestUtils.ts +++ b/__tests__/__packages__/cli-test-utils/src/TestUtils.ts @@ -12,7 +12,7 @@ import * as fs from "fs"; import { spawnSync, SpawnSyncReturns, ExecFileException } from "child_process"; import { ITestEnvironment } from "./environment/doc/response/ITestEnvironment"; -import { CommandProfiles, ICommandDefinition, IHandlerParameters } from "@zowe/imperative"; +import { ICommandDefinition, IHandlerParameters } from "@zowe/imperative"; /** * Execute a CLI script @@ -67,26 +67,6 @@ export function runCliScript(scriptPath: string, testEnvironment: ITestEnvironme } } -/** - * Check if stderr output is empty for profiles command. Ignores any message - * about profiles being deprecated. - * @deprecated Use `stripProfileDeprecationMessages` - */ -export function isStderrEmptyForProfilesCommand(output: Buffer): boolean { - return stripProfileDeprecationMessages(output).length === 0; -} - -/** - * Strip v1 profile deprecation messages from stderr output. - */ -export function stripProfileDeprecationMessages(stderr: Buffer | string): string { - return stderr.toString() - .replace(/Warning: The command 'profiles [a-z]+' is deprecated\./g, "") - .replace(/Recommended replacement: The 'config [a-z]+' command/g, "") - .replace(/Recommended replacement: Edit your Zowe V2 configuration\s+zowe\.config\.json/g, "") - .trim(); -} - /** * Type for handler data used to build mock IHandlerParameters object. * The type inherits from IHandlerParameters but is different: @@ -152,11 +132,9 @@ export function mockHandlerParameters(params: PartialHandlerParameters): IHandle arguments: { $0: "zowe", _: params.positionals || [], - ...(params.arguments || {}) + ...params.arguments || {} }, positionals: params.positionals || [], - // eslint-disable-next-line deprecation/deprecation - profiles: params.profiles || new CommandProfiles(new Map()), definition: params.definition, fullDefinition: params.definition, stdin: process.stdin, diff --git a/__tests__/__packages__/cli-test-utils/src/environment/TempTestProfiles.ts b/__tests__/__packages__/cli-test-utils/src/environment/TempTestProfiles.ts index 8596401a92..559cea7884 100644 --- a/__tests__/__packages__/cli-test-utils/src/environment/TempTestProfiles.ts +++ b/__tests__/__packages__/cli-test-utils/src/environment/TempTestProfiles.ts @@ -16,10 +16,9 @@ import * as fs from "fs"; import { v4 as uuidv4 } from "uuid"; -import { Config, ImperativeError, IO } from "@zowe/imperative"; +import { Config } from "@zowe/imperative"; import { ITestEnvironment } from "./doc/response/ITestEnvironment"; -import { runCliScript, stripProfileDeprecationMessages } from "../TestUtils"; /** * Utilities for creating and cleaning up temporary profiles for tests @@ -53,12 +52,6 @@ export class TempTestProfiles { `installed or linked globally so that '${TempTestProfiles.BINARY_NAME}' can be issued to create profiles and ` + `issue other commands.`; - /** - * Override for the ZOWE_CLI_TEST_OLD_PROFILES environment variable. If - * set to true, old-school profiles will be created instead of team config. - */ - public static forceOldProfiles: boolean = false; - /** * Create profiles for tests from data in the properties yaml file * @param {ITestEnvironment} testEnvironment - with working directory and test properties loaded @@ -73,11 +66,7 @@ export class TempTestProfiles { const profileNames: { [key: string]: string[] } = {}; this.log(testEnvironment, "Creating the following profileTypes: " + profileTypes); for (const profileType of profileTypes) { - if (this.usingTeamConfig) { - profileNames[profileType] = [await this.createV2Profile(testEnvironment, profileType)]; - } else { - profileNames[profileType] = [await this.createV1Profile(testEnvironment, profileType)]; - } + profileNames[profileType] = [await this.createV2Profile(testEnvironment, profileType)]; } return profileNames; } @@ -94,11 +83,7 @@ export class TempTestProfiles { this.log(testEnvironment, "Deleting the following profiles:\n" + JSON.stringify(profiles)); for (const profileType of Object.keys(profiles)) { for (const profileName of profiles[profileType]) { - if (this.usingTeamConfig) { - await this.deleteV2Profile(testEnvironment, profileType, profileName); - } else { - await this.deleteV1Profile(testEnvironment, profileType, profileName); - } + await this.deleteV2Profile(testEnvironment, profileType, profileName); } } } @@ -111,44 +96,6 @@ export class TempTestProfiles { */ private static readonly MAX_UUID_LENGTH = 20; - /** - * Whether new team config profiles should be used instead of old school - * profiles. - */ - private static get usingTeamConfig(): boolean { - if (this.forceOldProfiles) return false; - const envOldProfiles = process.env.ZOWE_CLI_TEST_OLD_PROFILES; - return envOldProfiles !== "1" && envOldProfiles?.toLowerCase() !== "true"; - } - - /** - * Helper to create a temporary old school profile from test properties - * @param {ITestEnvironment} testEnvironment - the test environment with env and working directory to use for output - * @returns {Promise} promise that resolves to the name of the created profile on success - * @throws errors if the profile creation fails - */ - private static async createV1Profile(testEnvironment: ITestEnvironment, profileType: string): Promise { - const profileName: string = uuidv4().substring(0, TempTestProfiles.MAX_UUID_LENGTH) + "_tmp_" + profileType; - let createProfileScript = this.SHEBANG + - `${this.BINARY_NAME} profiles create ${profileType} ${profileName}`; - for (const [k, v] of Object.entries(testEnvironment.systemTestProperties[profileType])) { - createProfileScript += ` ${(k.length > 1) ? "--" : "-"}${k} ${v}`; - } - const scriptPath = testEnvironment.workingDir + "_create_profile_" + profileName; - await IO.writeFileAsync(scriptPath, createProfileScript); - const output = runCliScript(scriptPath, testEnvironment, []); - if (output.status !== 0 || stripProfileDeprecationMessages(output.stderr).length > 0) { - throw new ImperativeError({ - msg: `Creation of ${profileType} profile '${profileName}' failed! You should delete the script: ` + - `'${scriptPath}' after reviewing it to check for possible errors. Stderr of the profile create ` + - `command:\n` + output.stderr.toString() + TempTestProfiles.GLOBAL_INSTALL_NOTE - }); - } - IO.deleteFile(scriptPath); - this.log(testEnvironment, `Created ${profileType} V1 profile '${profileName}'. Stdout from creation:\n${output.stdout.toString()}`); - return profileName; - } - /** * Helper to create a temporary team config profile from test properties * @internal @@ -176,31 +123,6 @@ export class TempTestProfiles { return profileName; } - /** - * Helper to delete a temporary old school profile - * @param {ITestEnvironment} testEnvironment - the test environment with env and working directory to use for output - * @param {string} profileType - the type of profile e.g. zosmf to - * @param {string} profileName - the name of the profile to delete - * @returns {Promise} promise that resolves to the name of the created profile on success - * @throws errors if the profile delete fails - */ - private static async deleteV1Profile(testEnvironment: ITestEnvironment, profileType: string, profileName: string): Promise { - const deleteProfileScript = this.SHEBANG + `${this.BINARY_NAME} profiles delete ${profileType} ${profileName} --force`; - const scriptPath = testEnvironment.workingDir + "_delete_profile_" + profileName; - await IO.writeFileAsync(scriptPath, deleteProfileScript); - const output = runCliScript(scriptPath, testEnvironment, []); - if (output.status !== 0 || stripProfileDeprecationMessages(output.stderr).length > 0) { - throw new ImperativeError({ - msg: "Deletion of " + profileType + " profile '" + profileName + "' failed! You should delete the script: '" + scriptPath + "' " + - "after reviewing it to check for possible errors. Stderr of the profile create command:\n" + output.stderr.toString() - + TempTestProfiles.GLOBAL_INSTALL_NOTE - }); - } - this.log(testEnvironment, `Deleted ${profileType} V1 profile '${profileName}'. Stdout from deletion:\n${output.stdout.toString()}`); - IO.deleteFile(scriptPath); - return profileName; - } - /** * Helper to delete a temporary team config profile * @internal @@ -216,8 +138,7 @@ export class TempTestProfiles { config.api.layers.activate(false, true); // Remove profile from config JSON - // eslint-disable-next-line deprecation/deprecation - config.delete(config.api.profiles.expandPath(profileName)); + config.delete(config.api.profiles.getProfilePathFromName(profileName)); if (config.api.layers.get().properties.defaults[profileType] === profileName) { config.delete(`defaults.${profileType}`); } diff --git a/__tests__/__packages__/cli-test-utils/src/environment/TestEnvironment.ts b/__tests__/__packages__/cli-test-utils/src/environment/TestEnvironment.ts index fc7503663a..2ebefad416 100644 --- a/__tests__/__packages__/cli-test-utils/src/environment/TestEnvironment.ts +++ b/__tests__/__packages__/cli-test-utils/src/environment/TestEnvironment.ts @@ -75,8 +75,7 @@ export class TestEnvironment { } // the result of the test environment setup so far is used to create profiles - TempTestProfiles.forceOldProfiles = params.createOldProfiles ?? false; - if (TempTestProfiles.forceOldProfiles || (params.tempProfileTypes?.length ?? 0 > 0)) { + if (params.tempProfileTypes?.length ?? 0 > 0) { result.tempProfiles = await TempTestProfiles.createProfiles(result, params.tempProfileTypes); } diff --git a/__tests__/__packages__/cli-test-utils/src/environment/doc/parms/ISetupEnvironmentParms.ts b/__tests__/__packages__/cli-test-utils/src/environment/doc/parms/ISetupEnvironmentParms.ts index be5aa2a5eb..08e865b35a 100644 --- a/__tests__/__packages__/cli-test-utils/src/environment/doc/parms/ISetupEnvironmentParms.ts +++ b/__tests__/__packages__/cli-test-utils/src/environment/doc/parms/ISetupEnvironmentParms.ts @@ -53,10 +53,4 @@ export interface ISetupEnvironmentParms { * you are trying to execute plugin commands installed into Zowe CLI. */ installPlugin?: boolean; - - /** - * Should old-school profiles be created instead of team config? - * Default: false - */ - createOldProfiles?: boolean; } diff --git a/__tests__/__scripts__/exitOnFailure.sh b/__tests__/__scripts__/exitOnFailure.sh new file mode 100644 index 0000000000..5e7beb8643 --- /dev/null +++ b/__tests__/__scripts__/exitOnFailure.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# function to exit if we encounter a bad return code +exitOnFailure () { + failureMsg=${1:?"First parm (failureMsg) is required."} + actualExitCode=${2:?"Second parm (actualExitCode) is required."} + goodExitCode=${3:-0} + if [ $actualExitCode != $goodExitCode ]; then + echo `basename $0`": $failureMsg" 1>&2 + exit $actualExitCode + fi +} diff --git a/__tests__/__src__/TestConstants.ts b/__tests__/__src__/TestConstants.ts new file mode 100644 index 0000000000..e87e89998a --- /dev/null +++ b/__tests__/__src__/TestConstants.ts @@ -0,0 +1,25 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +// Some test constants that are needed by multiple packages for unit tests + +// Mocked profile options to be added to args +export const UNIT_TEST_ZOSMF_PROF_OPTS = { + host: "somewhere.com", + port: "43443", + user: "someone", + password: "somesecret" +}; + +export const UNIT_TEST_TSO_PROF_OPTS = { + password: "fake", + account: "fake" +}; diff --git a/__tests__/__src__/mocks/ZosmfProfileMock.ts b/__tests__/__src__/mocks/ZosmfProfileMock.ts deleted file mode 100644 index 844d10a7f6..0000000000 --- a/__tests__/__src__/mocks/ZosmfProfileMock.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IProfile, CommandProfiles } from "@zowe/imperative"; -// Some test constants that are needed by multiple packages for unit tests - -// Mocked profile options to be added to args -export const UNIT_TEST_ZOSMF_PROF_OPTS = { - host: "somewhere.com", - port: "43443", - user: "someone", - password: "somesecret" -}; - -export const UNIT_TEST_TSO_PROF_OPTS = { - password: "fake", - account: "fake" -}; - -// A mocked profile map with zosmf profile -export const UNIT_TEST_PROFILE_MAP = new Map(); -UNIT_TEST_PROFILE_MAP.set( - "zosmf", [{ - name: "zosmf", - type: "zosmf", - ...UNIT_TEST_ZOSMF_PROF_OPTS - }] -); -export const UNIT_TEST_PROFILES_ZOSMF: CommandProfiles = new CommandProfiles(UNIT_TEST_PROFILE_MAP); - -// A mocked profile map with both -export const UNIT_TEST_PROFILE_MAP_ZOSMF_TSO = new Map(); -UNIT_TEST_PROFILE_MAP_ZOSMF_TSO.set( - "zosmf", [{ - name: "zosmf", - type: "zosmf", - ...UNIT_TEST_ZOSMF_PROF_OPTS - }] -); -UNIT_TEST_PROFILE_MAP_ZOSMF_TSO.set( - "tso", [{ - name: "tso", - type: "tso", - ...UNIT_TEST_TSO_PROF_OPTS - }] -); -export const UNIT_TEST_PROFILES_ZOSMF_TSO: CommandProfiles = new CommandProfiles(UNIT_TEST_PROFILE_MAP_ZOSMF_TSO); diff --git a/__tests__/__system__/cli/logging/LoggingCredentials.system.test.ts b/__tests__/__system__/cli/logging/LoggingCredentials.system.test.ts index 48c38cff51..f1c7180889 100644 --- a/__tests__/__system__/cli/logging/LoggingCredentials.system.test.ts +++ b/__tests__/__system__/cli/logging/LoggingCredentials.system.test.ts @@ -45,15 +45,15 @@ describe("Zowe CLI Logging", () => { const encodedAuth = Buffer.from(zosmfUsername + ":" + zosmfPassword).toString("base64"); // Grab both log files - const imperativeLogContents = fs.readFileSync(join(TEST_ENVIRONMENT.workingDir, "/imperative/logs/imperative.log")); - const zoweLogContents = fs.readFileSync(join(TEST_ENVIRONMENT.workingDir, "/" + Constants.LOG_LOCATION)); + const imperativeLogContents = fs.readFileSync(join(TEST_ENVIRONMENT.workingDir, "logs", "imperative.log")); + const zoweLogContents = fs.readFileSync(join(TEST_ENVIRONMENT.workingDir, Constants.LOG_LOCATION)); const tempTestLog = fs.readFileSync(join(TEST_ENVIRONMENT.workingDir, TempTestProfiles.LOG_FILE_NAME)); // ensure that the password and encoded auth does not appear in the imperative log expect(imperativeLogContents.indexOf(zosmfPassword)).not.toBeGreaterThanOrEqual(0); expect(imperativeLogContents.indexOf(encodedAuth)).not.toBeGreaterThanOrEqual(0); - // ensure that the password and encoded auth does not appear in the brightside log + // ensure that the password and encoded auth does not appear in the Zowe log expect(zoweLogContents.indexOf(zosmfPassword)).not.toBeGreaterThanOrEqual(0); expect(zoweLogContents.indexOf(encodedAuth)).not.toBeGreaterThanOrEqual(0); }); @@ -75,15 +75,15 @@ describe("Zowe CLI Logging", () => { expect(response.status).toBe(0); // Grab both log files - const imperativeLogContents = fs.readFileSync(join(TEST_ENVIRONMENT.workingDir, "/imperative/logs/imperative.log")); - const zoweLogContents = fs.readFileSync(join(TEST_ENVIRONMENT.workingDir, "/" + Constants.LOG_LOCATION)); + const imperativeLogContents = fs.readFileSync(join(TEST_ENVIRONMENT.workingDir, "logs", "imperative.log")); + const zoweLogContents = fs.readFileSync(join(TEST_ENVIRONMENT.workingDir, Constants.LOG_LOCATION)); const tempTestLog = fs.readFileSync(join(TEST_ENVIRONMENT.workingDir, TempTestProfiles.LOG_FILE_NAME)); // ensure that the password and encoded auth does not appear in the imperative log expect(imperativeLogContents.indexOf(zosmfPassword)).not.toBeGreaterThanOrEqual(0); expect(imperativeLogContents.indexOf(encodedAuth)).not.toBeGreaterThanOrEqual(0); - // ensure that the password and encoded auth does not appear in the brightside log + // ensure that the password and encoded auth does not appear in the Zowe log expect(zoweLogContents.indexOf(zosmfPassword)).not.toBeGreaterThanOrEqual(0); expect(zoweLogContents.indexOf(encodedAuth)).not.toBeGreaterThanOrEqual(0); }); diff --git a/__tests__/tsconfig.json b/__tests__/tsconfig.json index d40bd8139b..4d653bc801 100644 --- a/__tests__/tsconfig.json +++ b/__tests__/tsconfig.json @@ -1,33 +1,28 @@ { + // tsconfig for test files // "compilerOptions": { - "types": [ - "node", - "jest" - ], + "types": ["node", "jest"], + "lib": ["esnext"], "target": "es2015", "module": "commonjs", "declaration": true, "moduleResolution": "node", "noImplicitAny": true, - "outDir": "./lib", "preserveConstEnums": true, + "experimentalDecorators": true, "removeComments": false, "pretty": true, "sourceMap": true, - "newLine": "lf" + "newLine": "lf", + "esModuleInterop": true }, "include": [ "**/*.test.ts", "**/*.subtest.ts", "**/__tests__/**/*" ], - "files": [ - "../__types__/wontache.d.ts" - ], "exclude": [ "lib", - "__results__/", - "__snapshots__", "node_modules" ] -} \ No newline at end of file +} diff --git a/lerna.json b/lerna.json index ec13794f28..c581f3045f 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "command": { "publish": { "ignoreChanges": [ diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index b14de05952..fb04cdb143 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "@zowe/cli_monorepo", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -11,98 +11,79 @@ "__tests__/__packages__/*" ], "devDependencies": { - "@lerna-lite/changed": "^3.3.0", - "@lerna-lite/cli": "^3.3.0", - "@lerna-lite/list": "^3.3.0", - "@lerna-lite/run": "^3.3.0", - "@lerna-lite/version": "^3.3.0", - "@types/jest": "^29.0.0", - "@types/node": "^14.18.28", - "@types/which": "^2.0.1", - "@typescript-eslint/eslint-plugin": "^5.33.0", - "@typescript-eslint/parser": "^5.33.0", - "ansi-colors": "^4.1.1", + "@lerna-lite/changed": "^3.6.0", + "@lerna-lite/cli": "^3.6.0", + "@lerna-lite/list": "^3.6.0", + "@lerna-lite/run": "^3.6.0", + "@lerna-lite/version": "^3.6.0", + "@types/jest": "^29.5.12", + "@types/node": "^18.19.17", + "@types/which": "^3.0.4", + "@typescript-eslint/eslint-plugin": "^7.15.0", + "@typescript-eslint/parser": "^7.15.0", + "ansi-colors": "^4.1.2", "chalk": "^4.1.0", "env-cmd": "^10.1.0", "eslint": "^8.22.0", - "eslint-plugin-deprecation": "^2.0.0", - "eslint-plugin-jest": "^26.8.0", - "eslint-plugin-unused-imports": "^2.0.0", - "fancy-log": "^1.3.3", - "glob": "^7.2.3", - "husky": "^6.0.0", + "eslint-plugin-deprecation": "^3.0.0", + "eslint-plugin-jest": "^27.0.0", + "eslint-plugin-unused-imports": "^3.0.0", + "fancy-log": "^2.0.0", + "husky": "^9.0.0", "jest": "^29.0.0", "jest-environment-node": "^29.0.0", "jest-environment-node-debug": "^2.0.0", "jest-html-reporter": "^3.6.0", - "jest-junit": "^12.0.0", + "jest-junit": "^16.0.0", "jest-sonar-reporter": "^2.0.0", - "jest-stare": "^2.2.0", + "jest-stare": "^2.5.1", "js-yaml": "^4.1.0", - "jsonfile": "^4.0.0", - "madge": "^4.0.1", + "jsonfile": "^6.0.0", + "madge": "^7.0.0", "mustache": "^4.2.0", - "npm-lockfile": "^3.0.4", - "rimraf": "^2.6.3", - "shebang-regex": "^2.0.0", - "symlink-dir": "^5.1.1", - "ts-jest": "^29.0.0", + "npm-lockfile": "^3.0.7", + "rimraf": "^5.0.0", + "symlink-dir": "^6.0.0", + "ts-jest": "^29.1.5", "ts-node": "^7.0.1", - "typedoc": "^0.23.10", - "typescript": "^4.0.0" + "typedoc": "^0.26.3", + "typescript": "^5.5.3" } }, "__tests__/__packages__/cli-test-utils": { "name": "@zowe/cli-test-utils", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "license": "EPL-2.0", "dependencies": { "find-up": "^5.0.0", "js-yaml": "^4.0.0", - "rimraf": "^3.0.2", - "uuid": "^8.3.2" + "rimraf": "^5.0.0", + "uuid": "^10.0.0" }, "devDependencies": { - "@types/js-yaml": "^4.0.0", - "@types/uuid": "^8.3.0", - "@zowe/imperative": "5.27.1" + "@types/js-yaml": "^4.0.9", + "@types/uuid": "^10.0.0", + "@zowe/imperative": "8.0.0-next.202409111528" }, "peerDependencies": { - "@zowe/imperative": "^5.0.0" - } - }, - "__tests__/__packages__/cli-test-utils/node_modules/@zowe/imperative/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "extraneous": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@zowe/imperative": "^8.0.0-next" } }, - "__tests__/__packages__/cli-test-utils/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, + "__tests__/__packages__/cli-test-utils/node_modules/uuid": { + "version": "10.0.0", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "uuid": "dist/bin/uuid" } }, "node_modules/@ampproject/remapping": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -113,9 +94,8 @@ }, "node_modules/@babel/code-frame": { "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" @@ -126,9 +106,8 @@ }, "node_modules/@babel/code-frame/node_modules/ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -138,9 +117,8 @@ }, "node_modules/@babel/code-frame/node_modules/chalk": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -152,42 +130,37 @@ }, "node_modules/@babel/code-frame/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==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/@babel/code-frame/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==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/@babel/code-frame/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, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/code-frame/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, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -197,18 +170,16 @@ }, "node_modules/@babel/compat-data": { "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.0.tgz", - "integrity": "sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.23.5", @@ -236,24 +207,21 @@ }, "node_modules/@babel/core/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 + "dev": true, + "license": "MIT" }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", @@ -266,9 +234,8 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/compat-data": "^7.23.5", "@babel/helper-validator-option": "^7.23.5", @@ -282,36 +249,32 @@ }, "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/helper-environment-visitor": { "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.22.15", "@babel/types": "^7.23.0" @@ -322,9 +285,8 @@ }, "node_modules/@babel/helper-hoist-variables": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.22.5" }, @@ -334,9 +296,8 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.22.15" }, @@ -346,9 +307,8 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-module-imports": "^7.22.15", @@ -365,18 +325,16 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.22.5" }, @@ -386,9 +344,8 @@ }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.22.5" }, @@ -398,36 +355,32 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.0.tgz", - "integrity": "sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.24.0", "@babel/traverse": "^7.24.0", @@ -439,9 +392,8 @@ }, "node_modules/@babel/highlight": { "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", @@ -453,9 +405,8 @@ }, "node_modules/@babel/highlight/node_modules/ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -465,9 +416,8 @@ }, "node_modules/@babel/highlight/node_modules/chalk": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -479,42 +429,37 @@ }, "node_modules/@babel/highlight/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==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/@babel/highlight/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==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/@babel/highlight/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, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/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, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -524,9 +469,8 @@ }, "node_modules/@babel/parser": { "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz", - "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==", "dev": true, + "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -536,9 +480,8 @@ }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -548,9 +491,8 @@ }, "node_modules/@babel/plugin-syntax-bigint": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -560,9 +502,8 @@ }, "node_modules/@babel/plugin-syntax-class-properties": { "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -572,9 +513,8 @@ }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -584,9 +524,8 @@ }, "node_modules/@babel/plugin-syntax-json-strings": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -596,9 +535,8 @@ }, "node_modules/@babel/plugin-syntax-jsx": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -611,9 +549,8 @@ }, "node_modules/@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -623,9 +560,8 @@ }, "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -635,9 +571,8 @@ }, "node_modules/@babel/plugin-syntax-numeric-separator": { "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -647,9 +582,8 @@ }, "node_modules/@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -659,9 +593,8 @@ }, "node_modules/@babel/plugin-syntax-optional-catch-binding": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -671,9 +604,8 @@ }, "node_modules/@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -683,9 +615,8 @@ }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -698,9 +629,8 @@ }, "node_modules/@babel/plugin-syntax-typescript": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", - "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -713,9 +643,8 @@ }, "node_modules/@babel/runtime": { "version": "7.23.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.1.tgz", - "integrity": "sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==", "dev": true, + "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -725,9 +654,8 @@ }, "node_modules/@babel/template": { "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", - "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.23.5", "@babel/parser": "^7.24.0", @@ -739,9 +667,8 @@ }, "node_modules/@babel/traverse": { "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.0.tgz", - "integrity": "sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.23.5", "@babel/generator": "^7.23.6", @@ -760,18 +687,16 @@ }, "node_modules/@babel/traverse/node_modules/globals": { "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/types": { "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", @@ -783,14 +708,12 @@ }, "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 + "dev": true, + "license": "MIT" }, "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==", + "license": "MIT", "optional": true, "engines": { "node": ">=0.1.90" @@ -798,9 +721,8 @@ }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, + "license": "MIT", "optional": true, "peer": true, "dependencies": { @@ -812,9 +734,8 @@ }, "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, + "license": "MIT", "optional": true, "peer": true, "dependencies": { @@ -822,11 +743,22 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@dependents/detective-less": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "gonzales-pe": "^4.3.0", + "node-source-walk": "^6.0.1" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -837,28 +769,23 @@ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", "dev": true, + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", - "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", + "version": "2.1.4", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.0", + "espree": "^9.6.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -872,21 +799,27 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@gar/promisify": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@humanwhocodes/config-array": { - "version": "0.10.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", - "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", + "version": "0.11.14", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" @@ -894,9 +827,8 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -906,15 +838,21 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true + "version": "2.0.3", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@inquirer/figures": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/@isaacs/cliui": { "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -927,21 +865,9 @@ "node": ">=12" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, "node_modules/@isaacs/cliui/node_modules/ansi-styles": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -951,13 +877,11 @@ }, "node_modules/@isaacs/cliui/node_modules/emoji-regex": { "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + "license": "MIT" }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -972,8 +896,7 @@ }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -986,8 +909,7 @@ }, "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -1002,15 +924,13 @@ }, "node_modules/@isaacs/string-locale-compare": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz", - "integrity": "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, + "license": "ISC", "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -1024,18 +944,16 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -1046,9 +964,8 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -1059,9 +976,8 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -1071,9 +987,8 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -1086,9 +1001,8 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -1098,18 +1012,16 @@ }, "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, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@jest/console": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -1124,9 +1036,8 @@ }, "node_modules/@jest/console/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -1141,9 +1052,8 @@ }, "node_modules/@jest/core": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^29.7.0", "@jest/reporters": "^29.7.0", @@ -1186,23 +1096,10 @@ } } }, - "node_modules/@jest/core/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/@jest/core/node_modules/@jest/transform": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", @@ -1224,29 +1121,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/core/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@jest/core/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/@jest/core/node_modules/camelcase": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -1256,15 +1134,13 @@ }, "node_modules/@jest/core/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 + "dev": true, + "license": "MIT" }, "node_modules/@jest/core/node_modules/diff": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, + "license": "BSD-3-Clause", "optional": true, "peer": true, "engines": { @@ -1273,9 +1149,8 @@ }, "node_modules/@jest/core/node_modules/jest-config": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.7.0", @@ -1316,20 +1191,10 @@ } } }, - "node_modules/@jest/core/node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/@jest/core/node_modules/jest-haste-map": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", @@ -1352,18 +1217,16 @@ }, "node_modules/@jest/core/node_modules/jest-regex-util": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/core/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -1378,9 +1241,8 @@ }, "node_modules/@jest/core/node_modules/jest-validate": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "camelcase": "^6.2.0", @@ -1395,9 +1257,8 @@ }, "node_modules/@jest/core/node_modules/jest-worker": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", @@ -1408,31 +1269,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/core/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/@jest/core/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, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -1445,9 +1285,8 @@ }, "node_modules/@jest/core/node_modules/ts-node": { "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, + "license": "MIT", "optional": true, "peer": true, "dependencies": { @@ -1490,9 +1329,8 @@ }, "node_modules/@jest/core/node_modules/yn": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, + "license": "MIT", "optional": true, "peer": true, "engines": { @@ -1501,9 +1339,8 @@ }, "node_modules/@jest/environment": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", @@ -1516,9 +1353,8 @@ }, "node_modules/@jest/expect": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, + "license": "MIT", "dependencies": { "expect": "^29.7.0", "jest-snapshot": "^29.7.0" @@ -1529,9 +1365,8 @@ }, "node_modules/@jest/expect-utils": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, + "license": "MIT", "dependencies": { "jest-get-type": "^29.6.3" }, @@ -1539,20 +1374,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/expect-utils/node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/@jest/fake-timers": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", @@ -1567,9 +1392,8 @@ }, "node_modules/@jest/fake-timers/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -1584,9 +1408,8 @@ }, "node_modules/@jest/globals": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/expect": "^29.7.0", @@ -1599,9 +1422,8 @@ }, "node_modules/@jest/reporters": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, + "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.7.0", @@ -1642,9 +1464,8 @@ }, "node_modules/@jest/reporters/node_modules/@jest/transform": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", @@ -1668,15 +1489,13 @@ }, "node_modules/@jest/reporters/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 + "dev": true, + "license": "MIT" }, "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", - "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", @@ -1690,9 +1509,8 @@ }, "node_modules/@jest/reporters/node_modules/jest-haste-map": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", @@ -1715,18 +1533,16 @@ }, "node_modules/@jest/reporters/node_modules/jest-regex-util": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -1741,9 +1557,8 @@ }, "node_modules/@jest/reporters/node_modules/jest-worker": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", @@ -1756,9 +1571,8 @@ }, "node_modules/@jest/reporters/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, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -1771,9 +1585,8 @@ }, "node_modules/@jest/reporters/node_modules/v8-to-istanbul": { "version": "9.1.3", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", - "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==", "dev": true, + "license": "ISC", "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", @@ -1783,11 +1596,20 @@ "node": ">=10.12.0" } }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@jest/source-map": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", @@ -1799,18 +1621,16 @@ }, "node_modules/@jest/source-map/node_modules/callsites": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/@jest/test-result": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^29.7.0", "@jest/types": "^29.6.3", @@ -1823,9 +1643,8 @@ }, "node_modules/@jest/test-sequencer": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", @@ -1838,9 +1657,8 @@ }, "node_modules/@jest/test-sequencer/node_modules/jest-haste-map": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", @@ -1863,18 +1681,16 @@ }, "node_modules/@jest/test-sequencer/node_modules/jest-regex-util": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-sequencer/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -1889,9 +1705,8 @@ }, "node_modules/@jest/test-sequencer/node_modules/jest-worker": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", @@ -1904,9 +1719,8 @@ }, "node_modules/@jest/test-sequencer/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, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -1919,9 +1733,8 @@ }, "node_modules/@jest/types": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", @@ -1934,38 +1747,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/types/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@jest/types/node_modules/@types/yargs": { - "version": "17.0.13", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", - "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -1977,33 +1762,29 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -2011,38 +1792,35 @@ }, "node_modules/@kurkle/color": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", - "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@lerna-lite/changed": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/changed/-/changed-3.3.1.tgz", - "integrity": "sha512-wOpO3ob1gUlkxcle5NnnngVmgpK355q5wwRdRp8pIOf09FL+C1YSN1jiWWfRP+PaDsMNi6cNg8bgn9GkyhHSIg==", + "version": "3.6.0", "dev": true, + "license": "MIT", "dependencies": { - "@lerna-lite/cli": "3.3.1", - "@lerna-lite/core": "3.3.1", - "@lerna-lite/list": "3.3.1", - "@lerna-lite/listable": "3.3.1" + "@lerna-lite/cli": "3.6.0", + "@lerna-lite/core": "3.6.0", + "@lerna-lite/list": "3.6.0", + "@lerna-lite/listable": "3.6.0" }, "engines": { "node": "^18.0.0 || >=20.0.0" } }, "node_modules/@lerna-lite/cli": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/cli/-/cli-3.3.1.tgz", - "integrity": "sha512-tniFllcJtrR6SinS1AnDMzviZmnR1fInyIX1HZCIaDiiSz1O3FAM+QmrrFfSHl5HRaPpVGEPMP9KexTKZE+Csw==", + "version": "3.6.0", "dev": true, + "license": "MIT", "dependencies": { - "@lerna-lite/core": "3.3.1", - "@lerna-lite/init": "3.3.1", - "dedent": "^1.5.1", + "@lerna-lite/core": "3.6.0", + "@lerna-lite/init": "3.6.0", + "@lerna-lite/npmlog": "3.6.0", + "dedent": "^1.5.3", "dotenv": "^16.4.5", "import-local": "^3.1.0", "load-json-file": "^7.0.1", - "npmlog": "^7.0.1", "yargs": "^17.7.2" }, "bin": { @@ -2072,39 +1850,10 @@ } } }, - "node_modules/@lerna-lite/cli/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/@lerna-lite/cli/node_modules/dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", - "dev": true, - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, "node_modules/@lerna-lite/cli/node_modules/dotenv": { "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=12" }, @@ -2112,86 +1861,37 @@ "url": "https://dotenvx.com" } }, - "node_modules/@lerna-lite/cli/node_modules/load-json-file": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", - "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@lerna-lite/cli/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/@lerna-lite/cli/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/@lerna-lite/cli/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/@lerna-lite/core": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/core/-/core-3.3.1.tgz", - "integrity": "sha512-YkYVaHzdRqOFKtCZcWfRVg44lu1OXErzx9xKruKYjX6qHfUr0zqyNVm6tbzWGy9wPdU4VWw77KKzG+gtIEcGjA==", + "version": "3.6.0", "dev": true, + "license": "MIT", "dependencies": { - "@npmcli/run-script": "^7.0.4", + "@lerna-lite/npmlog": "^3.6.0", + "@npmcli/run-script": "^8.1.0", "chalk": "^5.3.0", "clone-deep": "^4.0.1", "config-chain": "^1.1.13", "cosmiconfig": "^9.0.0", - "dedent": "^1.5.1", + "dedent": "^1.5.3", "execa": "^8.0.1", "fs-extra": "^11.2.0", "glob-parent": "^6.0.2", "globby": "^14.0.1", - "inquirer": "^9.2.15", + "inquirer": "^9.3.0", "is-ci": "^3.0.1", "json5": "^2.2.3", "load-json-file": "^7.0.1", - "minimatch": "^9.0.3", - "npm-package-arg": "^11.0.1", - "npmlog": "^7.0.1", - "p-map": "^7.0.1", + "minimatch": "^9.0.5", + "npm-package-arg": "^11.0.2", + "p-map": "^7.0.2", "p-queue": "^8.0.1", "resolve-from": "^5.0.0", - "semver": "^7.6.0", + "semver": "^7.6.2", "slash": "^5.1.0", "strong-log-transformer": "^2.1.0", "write-file-atomic": "^5.0.1", "write-json-file": "^5.0.0", - "write-pkg": "^6.0.1" + "write-package": "^7.0.1" }, "engines": { "node": "^18.0.0 || >=20.0.0" @@ -2202,10 +1902,9 @@ } }, "node_modules/@lerna-lite/core/node_modules/@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "version": "3.1.1", "dev": true, + "license": "ISC", "dependencies": { "semver": "^7.3.5" }, @@ -2215,25 +1914,23 @@ }, "node_modules/@lerna-lite/core/node_modules/@npmcli/node-gyp": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", - "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", "dev": true, + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/@lerna-lite/core/node_modules/@npmcli/package-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.0.0.tgz", - "integrity": "sha512-OI2zdYBLhQ7kpNPaJxiflofYIpkNLi+lnGdzqUOfRmCF3r2l1nadcjtCYMJKv/Utm/ZtlffaUuTiAktPHbc17g==", + "version": "5.2.0", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/git": "^5.0.0", "glob": "^10.2.2", "hosted-git-info": "^7.0.0", "json-parse-even-better-errors": "^3.0.0", "normalize-package-data": "^6.0.0", - "proc-log": "^3.0.0", + "proc-log": "^4.0.0", "semver": "^7.5.3" }, "engines": { @@ -2241,15 +1938,15 @@ } }, "node_modules/@lerna-lite/core/node_modules/@npmcli/run-script": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-7.0.4.tgz", - "integrity": "sha512-9ApYM/3+rBt9V80aYg6tZfzj3UWdiYyCt7gJUD1VJKvWF5nwKDSICXbYIQbspFTq6TOpbsEtIC0LArB8d9PFmg==", + "version": "8.1.0", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/node-gyp": "^3.0.0", "@npmcli/package-json": "^5.0.0", "@npmcli/promise-spawn": "^7.0.0", "node-gyp": "^10.0.0", + "proc-log": "^4.0.0", "which": "^4.0.0" }, "engines": { @@ -2258,36 +1955,24 @@ }, "node_modules/@lerna-lite/core/node_modules/abbrev": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", "dev": true, + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/@lerna-lite/core/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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, - "node_modules/@lerna-lite/core/node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "dependencies": { - "semver": "^7.0.0" - } - }, "node_modules/@lerna-lite/core/node_modules/cacache": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", - "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", + "version": "18.0.3", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/fs": "^3.1.0", "fs-minipass": "^3.0.0", @@ -2308,9 +1993,8 @@ }, "node_modules/@lerna-lite/core/node_modules/cacache/node_modules/p-map": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, + "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" }, @@ -2323,9 +2007,8 @@ }, "node_modules/@lerna-lite/core/node_modules/chalk": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, + "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -2333,75 +2016,10 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@lerna-lite/core/node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@lerna-lite/core/node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", - "dev": true, - "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@lerna-lite/core/node_modules/dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", - "dev": true, - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/@lerna-lite/core/node_modules/detect-indent": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", - "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", - "dev": true, - "engines": { - "node": ">=12.20" - } - }, - "node_modules/@lerna-lite/core/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true - }, "node_modules/@lerna-lite/core/node_modules/execa": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", @@ -2420,53 +2038,10 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/@lerna-lite/core/node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/@lerna-lite/core/node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@lerna-lite/core/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/@lerna-lite/core/node_modules/fs-minipass": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", "dev": true, + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -2476,9 +2051,8 @@ }, "node_modules/@lerna-lite/core/node_modules/get-stream": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -2487,22 +2061,22 @@ } }, "node_modules/@lerna-lite/core/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.4.2", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -2510,9 +2084,8 @@ }, "node_modules/@lerna-lite/core/node_modules/glob-parent": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -2521,10 +2094,9 @@ } }, "node_modules/@lerna-lite/core/node_modules/globby": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", - "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", + "version": "14.0.2", "dev": true, + "license": "MIT", "dependencies": { "@sindresorhus/merge-streams": "^2.1.0", "fast-glob": "^3.3.2", @@ -2540,146 +2112,62 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna-lite/core/node_modules/hosted-git-info": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", - "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", - "dev": true, - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, "node_modules/@lerna-lite/core/node_modules/human-signals": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=16.17.0" } }, - "node_modules/@lerna-lite/core/node_modules/inquirer": { - "version": "9.2.15", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.15.tgz", - "integrity": "sha512-vI2w4zl/mDluHt9YEQ/543VTCwPKWiHzKtm9dM2V0NdFcqEexDAjUHzO1oA60HRNaVifGXXM1tRRNluLVHa0Kg==", + "node_modules/@lerna-lite/core/node_modules/is-stream": { + "version": "3.0.0", "dev": true, - "dependencies": { - "@ljharb/through": "^2.3.12", - "ansi-escapes": "^4.3.2", - "chalk": "^5.3.0", - "cli-cursor": "^3.1.0", - "cli-width": "^4.1.0", - "external-editor": "^3.1.0", - "figures": "^3.2.0", - "lodash": "^4.17.21", - "mute-stream": "1.0.0", - "ora": "^5.4.1", - "run-async": "^3.0.0", - "rxjs": "^7.8.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^6.2.0" - }, + "license": "MIT", "engines": { - "node": ">=18" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna-lite/core/node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/@lerna-lite/core/node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "node_modules/@lerna-lite/core/node_modules/isexe": { + "version": "3.1.1", "dev": true, + "license": "ISC", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=16" } }, - "node_modules/@lerna-lite/core/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "node_modules/@lerna-lite/core/node_modules/jackspeak": { + "version": "3.4.0", "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@lerna-lite/core/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true, - "engines": { - "node": ">=16" - } - }, - "node_modules/@lerna-lite/core/node_modules/json-parse-even-better-errors": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", - "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@lerna-lite/core/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" + "url": "https://github.com/sponsors/isaacs" }, "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@lerna-lite/core/node_modules/lines-and-columns": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", - "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/@lerna-lite/core/node_modules/load-json-file": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", - "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", + "node_modules/@lerna-lite/core/node_modules/json-parse-even-better-errors": { + "version": "3.0.2", "dev": true, + "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/@lerna-lite/core/node_modules/make-fetch-happen": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", - "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", + "version": "13.0.1", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/agent": "^2.0.0", "cacache": "^18.0.0", @@ -2690,6 +2178,7 @@ "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", + "proc-log": "^4.2.0", "promise-retry": "^2.0.1", "ssri": "^10.0.0" }, @@ -2699,9 +2188,8 @@ }, "node_modules/@lerna-lite/core/node_modules/mimic-fn": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -2710,10 +2198,9 @@ } }, "node_modules/@lerna-lite/core/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.5", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -2725,19 +2212,17 @@ } }, "node_modules/@lerna-lite/core/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.2", "dev": true, + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/@lerna-lite/core/node_modules/minipass-collect": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", "dev": true, + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -2746,10 +2231,9 @@ } }, "node_modules/@lerna-lite/core/node_modules/minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "version": "3.0.5", "dev": true, + "license": "MIT", "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", @@ -2762,20 +2246,10 @@ "encoding": "^0.1.13" } }, - "node_modules/@lerna-lite/core/node_modules/mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/@lerna-lite/core/node_modules/node-gyp": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz", - "integrity": "sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==", + "version": "10.1.0", "dev": true, + "license": "MIT", "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", @@ -2795,56 +2269,32 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/@lerna-lite/core/node_modules/nopt": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", - "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", + "node_modules/@lerna-lite/core/node_modules/node-gyp/node_modules/proc-log": { + "version": "3.0.0", "dev": true, - "dependencies": { - "abbrev": "^2.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@lerna-lite/core/node_modules/normalize-package-data": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.0.tgz", - "integrity": "sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==", + "node_modules/@lerna-lite/core/node_modules/nopt": { + "version": "7.2.1", "dev": true, + "license": "ISC", "dependencies": { - "hosted-git-info": "^7.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" + "abbrev": "^2.0.0" }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/@lerna-lite/core/node_modules/npm-package-arg": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", - "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", - "dev": true, - "dependencies": { - "hosted-git-info": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" + "bin": { + "nopt": "bin/nopt.js" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/@lerna-lite/core/node_modules/npm-run-path": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^4.0.0" }, @@ -2857,9 +2307,8 @@ }, "node_modules/@lerna-lite/core/node_modules/onetime": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^4.0.0" }, @@ -2871,26 +2320,9 @@ } }, "node_modules/@lerna-lite/core/node_modules/p-map": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.1.tgz", - "integrity": "sha512-2wnaR0XL/FDOj+TgpDuRb2KTjLnu3Fma6b1ZUwGY7LcqenMcvP/YFpjpbPKY6WVGsbuJZRuoUz8iPrt8ORnAFw==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@lerna-lite/core/node_modules/p-queue": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.0.1.tgz", - "integrity": "sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==", + "version": "7.0.2", "dev": true, - "dependencies": { - "eventemitter3": "^5.0.1", - "p-timeout": "^6.1.2" - }, + "license": "MIT", "engines": { "node": ">=18" }, @@ -2898,23 +2330,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna-lite/core/node_modules/p-timeout": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", - "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@lerna-lite/core/node_modules/path-key": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -2924,9 +2343,8 @@ }, "node_modules/@lerna-lite/core/node_modules/path-type": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -2935,104 +2353,17 @@ } }, "node_modules/@lerna-lite/core/node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "version": "4.2.0", "dev": true, + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@lerna-lite/core/node_modules/read-pkg": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-8.1.0.tgz", - "integrity": "sha512-PORM8AgzXeskHO/WEv312k9U03B8K9JSiWF/8N9sUuFjBa+9SF2u6K7VClzXwDXab51jCd8Nd36CNM+zR97ScQ==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.1", - "normalize-package-data": "^6.0.0", - "parse-json": "^7.0.0", - "type-fest": "^4.2.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@lerna-lite/core/node_modules/read-pkg/node_modules/parse-json": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.1.tgz", - "integrity": "sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.21.4", - "error-ex": "^1.3.2", - "json-parse-even-better-errors": "^3.0.0", - "lines-and-columns": "^2.0.3", - "type-fest": "^3.8.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@lerna-lite/core/node_modules/read-pkg/node_modules/parse-json/node_modules/type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@lerna-lite/core/node_modules/run-async": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", - "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/@lerna-lite/core/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@lerna-lite/core/node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@lerna-lite/core/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, + "license": "ISC", "engines": { "node": ">=14" }, @@ -3042,9 +2373,8 @@ }, "node_modules/@lerna-lite/core/node_modules/slash": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.16" }, @@ -3052,26 +2382,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna-lite/core/node_modules/sort-keys": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.0.0.tgz", - "integrity": "sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==", - "dev": true, - "dependencies": { - "is-plain-obj": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@lerna-lite/core/node_modules/ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "version": "10.0.6", "dev": true, + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -3081,9 +2395,8 @@ }, "node_modules/@lerna-lite/core/node_modules/strip-final-newline": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -3091,38 +2404,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna-lite/core/node_modules/type-fest": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.11.1.tgz", - "integrity": "sha512-MFMf6VkEVZAETidGGSYW2B1MjXbGX+sWIywn2QPEaJ3j08V+MwVRHMXtf2noB8ENJaD0LIun9wh5Z6OPNf1QzQ==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@lerna-lite/core/node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true, - "optional": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/@lerna-lite/core/node_modules/unique-filename": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", "dev": true, + "license": "ISC", "dependencies": { "unique-slug": "^4.0.0" }, @@ -3132,9 +2417,8 @@ }, "node_modules/@lerna-lite/core/node_modules/unique-slug": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, @@ -3142,23 +2426,10 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@lerna-lite/core/node_modules/validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", - "dev": true, - "dependencies": { - "builtins": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@lerna-lite/core/node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "node_modules/@lerna-lite/core/node_modules/which": { + "version": "4.0.0", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^3.1.1" }, @@ -3169,25 +2440,10 @@ "node": "^16.13.0 || >=18.0.0" } }, - "node_modules/@lerna-lite/core/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@lerna-lite/core/node_modules/write-file-atomic": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^4.0.1" @@ -3196,138 +2452,125 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@lerna-lite/core/node_modules/write-json-file": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-5.0.0.tgz", - "integrity": "sha512-ddSsCLa4aQ3kI21BthINo4q905/wfhvQ3JL3774AcRjBaiQmfn5v4rw77jQ7T6CmAit9VOQO+FsLyPkwxoB1fw==", + "node_modules/@lerna-lite/filter-packages": { + "version": "3.6.0", "dev": true, + "license": "MIT", "dependencies": { - "detect-indent": "^7.0.0", - "is-plain-obj": "^4.0.0", - "sort-keys": "^5.0.0", - "write-file-atomic": "^3.0.3" + "@lerna-lite/core": "3.6.0", + "@lerna-lite/npmlog": "^3.6.0", + "multimatch": "^7.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.0.0 || >=20.0.0" } }, - "node_modules/@lerna-lite/core/node_modules/write-json-file/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/@lerna-lite/core/node_modules/write-json-file/node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "node_modules/@lerna-lite/init": { + "version": "3.6.0", "dev": true, + "license": "MIT", "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "@lerna-lite/core": "3.6.0", + "fs-extra": "^11.2.0", + "p-map": "^7.0.2", + "write-json-file": "^5.0.0" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" } }, - "node_modules/@lerna-lite/core/node_modules/write-pkg": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-6.0.1.tgz", - "integrity": "sha512-ZwKp0+CQCNrJbhHStRy6IVDnVjvD4gYy6MhQLKgBnl85oaiTNXhvtuox7AqvOSf1wta0YW4U5JidjpJnd1i8TA==", + "node_modules/@lerna-lite/init/node_modules/p-map": { + "version": "7.0.2", "dev": true, - "dependencies": { - "deepmerge-ts": "^5.1.0", - "read-pkg": "^8.1.0", - "sort-keys": "^5.0.0", - "type-fest": "^4.6.0", - "write-json-file": "^5.0.0" - }, + "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna-lite/core/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@lerna-lite/filter-packages": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/filter-packages/-/filter-packages-3.3.1.tgz", - "integrity": "sha512-YHK6TazjA2yJsWnsKuHbb8/pobLWjEwv4HaHUU3n9ZiRkfgckRPZV2MYQFfySnTaTJDqUHMVuSmnfaUugTr03w==", + "node_modules/@lerna-lite/list": { + "version": "3.6.0", "dev": true, + "license": "MIT", "dependencies": { - "@lerna-lite/core": "3.3.1", - "multimatch": "^7.0.0", - "npmlog": "^7.0.1" + "@lerna-lite/cli": "3.6.0", + "@lerna-lite/core": "3.6.0", + "@lerna-lite/filter-packages": "3.6.0", + "@lerna-lite/listable": "3.6.0" }, "engines": { "node": "^18.0.0 || >=20.0.0" } }, - "node_modules/@lerna-lite/filter-packages/node_modules/array-differ": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-4.0.0.tgz", - "integrity": "sha512-Q6VPTLMsmXZ47ENG3V+wQyZS1ZxXMxFyYzA+Z/GMrJ6yIutAIEf9wTyroTzmGjNfox9/h3GdGBCVh43GVFx4Uw==", + "node_modules/@lerna-lite/listable": { + "version": "3.6.0", "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "license": "MIT", + "dependencies": { + "@lerna-lite/core": "3.6.0", + "chalk": "^5.3.0", + "columnify": "^1.6.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^18.0.0 || >=20.0.0" } }, - "node_modules/@lerna-lite/filter-packages/node_modules/array-union": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", - "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", + "node_modules/@lerna-lite/listable/node_modules/chalk": { + "version": "5.3.0", "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@lerna-lite/filter-packages/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==", + "node_modules/@lerna-lite/npmlog": { + "version": "3.6.0", "dev": true, + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "aproba": "^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "set-blocking": "^2.0.0", + "signal-exit": "^4.1.0", + "string-width": "^7.1.0", + "strip-ansi": "^7.1.0", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" } }, - "node_modules/@lerna-lite/filter-packages/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/@lerna-lite/npmlog/node_modules/emoji-regex": { + "version": "10.3.0", "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "license": "MIT" + }, + "node_modules/@lerna-lite/npmlog/node_modules/signal-exit": { + "version": "4.1.0", + "dev": true, + "license": "ISC", "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=14" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@lerna-lite/filter-packages/node_modules/multimatch": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-7.0.0.tgz", - "integrity": "sha512-SYU3HBAdF4psHEL/+jXDKHO95/m5P2RvboHT2Y0WtTttvJLP4H/2WS9WlQPFvF6C8d6SpLw8vjCnQOnVIVOSJQ==", + "node_modules/@lerna-lite/npmlog/node_modules/string-width": { + "version": "7.2.0", "dev": true, + "license": "MIT", "dependencies": { - "array-differ": "^4.0.0", - "array-union": "^3.0.1", - "minimatch": "^9.0.3" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { "node": ">=18" @@ -3336,74 +2579,67 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna-lite/init": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/init/-/init-3.3.1.tgz", - "integrity": "sha512-dYTEfwz4xv43BeILWjWxijhpTcKtHqIQEx1QVEmzOVJu6lbpATkbFYQ5DO4BXElyx/5hjNLHptKnDIen9T5Peg==", + "node_modules/@lerna-lite/npmlog/node_modules/strip-ansi": { + "version": "7.1.0", "dev": true, + "license": "MIT", "dependencies": { - "@lerna-lite/core": "3.3.1", - "fs-extra": "^11.2.0", - "p-map": "^7.0.1", - "write-json-file": "^5.0.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@lerna-lite/init/node_modules/detect-indent": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", - "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", + "node_modules/@lerna-lite/profiler": { + "version": "3.6.0", "dev": true, + "license": "MIT", + "dependencies": { + "@lerna-lite/core": "3.6.0", + "@lerna-lite/npmlog": "3.6.0", + "fs-extra": "^11.2.0", + "upath": "^2.0.1" + }, "engines": { - "node": ">=12.20" + "node": "^18.0.0 || >=20.0.0" } }, - "node_modules/@lerna-lite/init/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "node_modules/@lerna-lite/run": { + "version": "3.6.0", "dev": true, + "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@lerna-lite/cli": "3.6.0", + "@lerna-lite/core": "3.6.0", + "@lerna-lite/filter-packages": "3.6.0", + "@lerna-lite/npmlog": "3.6.0", + "@lerna-lite/profiler": "3.6.0", + "chalk": "^5.3.0", + "fs-extra": "^11.2.0", + "p-map": "^7.0.2" }, "engines": { - "node": ">=14.14" + "node": "^18.0.0 || >=20.0.0" } }, - "node_modules/@lerna-lite/init/node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "node_modules/@lerna-lite/run/node_modules/chalk": { + "version": "5.3.0", "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@lerna-lite/init/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/@lerna-lite/run/node_modules/p-map": { + "version": "7.0.2", "dev": true, "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@lerna-lite/init/node_modules/p-map": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.1.tgz", - "integrity": "sha512-2wnaR0XL/FDOj+TgpDuRb2KTjLnu3Fma6b1ZUwGY7LcqenMcvP/YFpjpbPKY6WVGsbuJZRuoUz8iPrt8ORnAFw==", - "dev": true, "engines": { "node": ">=18" }, @@ -3411,85 +2647,69 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna-lite/init/node_modules/sort-keys": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.0.0.tgz", - "integrity": "sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==", + "node_modules/@lerna-lite/version": { + "version": "3.6.0", "dev": true, + "license": "MIT", "dependencies": { - "is-plain-obj": "^4.0.0" + "@lerna-lite/cli": "3.6.0", + "@lerna-lite/core": "3.6.0", + "@lerna-lite/npmlog": "^3.6.0", + "@octokit/plugin-enterprise-rest": "^6.0.1", + "@octokit/rest": "^21.0.0", + "chalk": "^5.3.0", + "conventional-changelog-angular": "^7.0.0", + "conventional-changelog-core": "^7.0.0", + "conventional-changelog-writer": "^7.0.1", + "conventional-commits-parser": "^5.0.0", + "conventional-recommended-bump": "^9.0.0", + "dedent": "^1.5.3", + "fs-extra": "^11.2.0", + "get-stream": "^9.0.1", + "git-url-parse": "^14.0.0", + "graceful-fs": "^4.2.11", + "is-stream": "^4.0.1", + "load-json-file": "^7.0.1", + "make-dir": "^5.0.0", + "minimatch": "^9.0.5", + "new-github-release-url": "^2.0.0", + "node-fetch": "^3.3.2", + "npm-package-arg": "^11.0.2", + "p-limit": "^5.0.0", + "p-map": "^7.0.2", + "p-pipe": "^4.0.0", + "p-reduce": "^3.0.0", + "pify": "^6.1.0", + "semver": "^7.6.2", + "slash": "^5.1.0", + "temp-dir": "^3.0.0", + "uuid": "^10.0.0", + "write-json-file": "^5.0.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@lerna-lite/init/node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "node": "^18.0.0 || >=20.0.0" } }, - "node_modules/@lerna-lite/init/node_modules/write-json-file": { + "node_modules/@lerna-lite/version/node_modules/@hutson/parse-repository-url": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-5.0.0.tgz", - "integrity": "sha512-ddSsCLa4aQ3kI21BthINo4q905/wfhvQ3JL3774AcRjBaiQmfn5v4rw77jQ7T6CmAit9VOQO+FsLyPkwxoB1fw==", - "dev": true, - "dependencies": { - "detect-indent": "^7.0.0", - "is-plain-obj": "^4.0.0", - "sort-keys": "^5.0.0", - "write-file-atomic": "^3.0.3" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@lerna-lite/list": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/list/-/list-3.3.1.tgz", - "integrity": "sha512-F5/a2W5PKF2fpLqmLMi58dEdJ2F4mvAlywXA4FRc21T7mYNnJ095oVskruwHlEVZE7jUKitZjM10EVG8sG3HEw==", "dev": true, - "dependencies": { - "@lerna-lite/cli": "3.3.1", - "@lerna-lite/core": "3.3.1", - "@lerna-lite/filter-packages": "3.3.1", - "@lerna-lite/listable": "3.3.1" - }, + "license": "Apache-2.0", "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": ">=10.13.0" } }, - "node_modules/@lerna-lite/listable": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/listable/-/listable-3.3.1.tgz", - "integrity": "sha512-pMk97xYxPU6opebGHo5m01kr6kbHmoi96SGEM63V9v4UtFrCFQY4UXemrTDZLkzz6WfqaXFLzvx6PGK9lKhnCA==", + "node_modules/@lerna-lite/version/node_modules/brace-expansion": { + "version": "2.0.1", "dev": true, + "license": "MIT", "dependencies": { - "@lerna-lite/core": "3.3.1", - "chalk": "^5.3.0", - "columnify": "^1.6.0" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" + "balanced-match": "^1.0.0" } }, - "node_modules/@lerna-lite/listable/node_modules/chalk": { + "node_modules/@lerna-lite/version/node_modules/chalk": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, + "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -3497,360 +2717,10 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@lerna-lite/profiler": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/profiler/-/profiler-3.3.1.tgz", - "integrity": "sha512-EZYu512G+pdgn58BJwBaqfiYMqfhiYKrWNf8bVsEYI8nLSrCgfyq9ZSxMzz+QRx6sv//41KhkACpc2RU9V4yyA==", - "dev": true, - "dependencies": { - "@lerna-lite/core": "3.3.1", - "fs-extra": "^11.2.0", - "npmlog": "^7.0.1", - "upath": "^2.0.1" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - } - }, - "node_modules/@lerna-lite/profiler/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@lerna-lite/profiler/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@lerna-lite/run": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/run/-/run-3.3.1.tgz", - "integrity": "sha512-ycuekq6MTPuKOBzwhwcjSX3N1YfjwSH39OyixF8WKmaIoOQM+ogXTU6tjOGcUxVNycNpm1Zx5SgHZmS/APbBKA==", - "dev": true, - "dependencies": { - "@lerna-lite/cli": "3.3.1", - "@lerna-lite/core": "3.3.1", - "@lerna-lite/filter-packages": "3.3.1", - "@lerna-lite/profiler": "3.3.1", - "chalk": "^5.3.0", - "fs-extra": "^11.2.0", - "npmlog": "^7.0.1", - "p-map": "^7.0.1" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - } - }, - "node_modules/@lerna-lite/run/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@lerna-lite/run/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@lerna-lite/run/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@lerna-lite/run/node_modules/p-map": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.1.tgz", - "integrity": "sha512-2wnaR0XL/FDOj+TgpDuRb2KTjLnu3Fma6b1ZUwGY7LcqenMcvP/YFpjpbPKY6WVGsbuJZRuoUz8iPrt8ORnAFw==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@lerna-lite/version": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/version/-/version-3.3.1.tgz", - "integrity": "sha512-0Kes5H0H8+tZSTLMTf5ArZTIijROSwgvJsnd5o7z6XvYZM8cq9ED63tpzgX9GKXyqnjZH4mlHpcQr5lpmABJFA==", - "dev": true, - "dependencies": { - "@lerna-lite/cli": "3.3.1", - "@lerna-lite/core": "3.3.1", - "@octokit/plugin-enterprise-rest": "^6.0.1", - "@octokit/rest": "^20.0.2", - "chalk": "^5.3.0", - "conventional-changelog-angular": "^7.0.0", - "conventional-changelog-core": "^7.0.0", - "conventional-changelog-writer": "^7.0.1", - "conventional-commits-parser": "^5.0.0", - "conventional-recommended-bump": "^9.0.0", - "dedent": "^1.5.1", - "fs-extra": "^11.2.0", - "get-stream": "^8.0.1", - "git-url-parse": "^14.0.0", - "graceful-fs": "^4.2.11", - "is-stream": "^4.0.1", - "load-json-file": "^7.0.1", - "make-dir": "^4.0.0", - "minimatch": "^9.0.3", - "new-github-release-url": "^2.0.0", - "node-fetch": "^3.3.2", - "npm-package-arg": "^11.0.1", - "npmlog": "^7.0.1", - "p-map": "^7.0.1", - "p-pipe": "^4.0.0", - "p-reduce": "^3.0.0", - "pify": "^6.1.0", - "semver": "^7.6.0", - "slash": "^5.1.0", - "temp-dir": "^3.0.0", - "uuid": "^9.0.1", - "write-json-file": "^5.0.0" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - } - }, - "node_modules/@lerna-lite/version/node_modules/@hutson/parse-repository-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-5.0.0.tgz", - "integrity": "sha512-e5+YUKENATs1JgYHMzTr2MW/NDcXGfYFAuOQU8gJgF/kEh4EqKgfGrfLI67bMD4tbhZVlkigz/9YYwWcbOFthg==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@lerna-lite/version/node_modules/@octokit/auth-token": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", - "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", - "dev": true, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@lerna-lite/version/node_modules/@octokit/core": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.1.0.tgz", - "integrity": "sha512-BDa2VAMLSh3otEiaMJ/3Y36GU4qf6GI+VivQ/P41NC6GHcdxpKlqV0ikSZ5gdQsmS3ojXeRx5vasgNTinF0Q4g==", - "dev": true, - "dependencies": { - "@octokit/auth-token": "^4.0.0", - "@octokit/graphql": "^7.0.0", - "@octokit/request": "^8.0.2", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^12.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@lerna-lite/version/node_modules/@octokit/endpoint": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.4.tgz", - "integrity": "sha512-DWPLtr1Kz3tv8L0UvXTDP1fNwM0S+z6EJpRcvH66orY6Eld4XBMCSYsaWp4xIm61jTWxK68BrR7ibO+vSDnZqw==", - "dev": true, - "dependencies": { - "@octokit/types": "^12.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@lerna-lite/version/node_modules/@octokit/graphql": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.2.tgz", - "integrity": "sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==", - "dev": true, - "dependencies": { - "@octokit/request": "^8.0.1", - "@octokit/types": "^12.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@lerna-lite/version/node_modules/@octokit/openapi-types": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", - "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", - "dev": true - }, - "node_modules/@lerna-lite/version/node_modules/@octokit/plugin-paginate-rest": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz", - "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==", - "dev": true, - "dependencies": { - "@octokit/types": "^12.6.0" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": "5" - } - }, - "node_modules/@lerna-lite/version/node_modules/@octokit/plugin-request-log": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.1.tgz", - "integrity": "sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==", - "dev": true, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": "5" - } - }, - "node_modules/@lerna-lite/version/node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", - "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", - "dev": true, - "dependencies": { - "@octokit/types": "^12.6.0" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": "5" - } - }, - "node_modules/@lerna-lite/version/node_modules/@octokit/request": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.2.0.tgz", - "integrity": "sha512-exPif6x5uwLqv1N1irkLG1zZNJkOtj8bZxuVHd71U5Ftuxf2wGNvAJyNBcPbPC+EBzwYEbBDdSFb8EPcjpYxPQ==", - "dev": true, - "dependencies": { - "@octokit/endpoint": "^9.0.0", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^12.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@lerna-lite/version/node_modules/@octokit/request-error": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.1.tgz", - "integrity": "sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==", - "dev": true, - "dependencies": { - "@octokit/types": "^12.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@lerna-lite/version/node_modules/@octokit/rest": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz", - "integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==", - "dev": true, - "dependencies": { - "@octokit/core": "^5.0.0", - "@octokit/plugin-paginate-rest": "^9.0.0", - "@octokit/plugin-request-log": "^4.0.0", - "@octokit/plugin-rest-endpoint-methods": "^10.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@lerna-lite/version/node_modules/@octokit/types": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", - "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", - "dev": true, - "dependencies": { - "@octokit/openapi-types": "^20.0.0" - } - }, - "node_modules/@lerna-lite/version/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/@lerna-lite/version/node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "dependencies": { - "semver": "^7.0.0" - } - }, - "node_modules/@lerna-lite/version/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@lerna-lite/version/node_modules/conventional-changelog-angular": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", - "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", + "node_modules/@lerna-lite/version/node_modules/conventional-changelog-angular": { + "version": "7.0.0", "dev": true, + "license": "ISC", "dependencies": { "compare-func": "^2.0.0" }, @@ -3860,9 +2730,8 @@ }, "node_modules/@lerna-lite/version/node_modules/conventional-changelog-core": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-7.0.0.tgz", - "integrity": "sha512-UYgaB1F/COt7VFjlYKVE/9tTzfU3VUq47r6iWf6lM5T7TlOxr0thI63ojQueRLIpVbrtHK4Ffw+yQGduw2Bhdg==", "dev": true, + "license": "MIT", "dependencies": { "@hutson/parse-repository-url": "^5.0.0", "add-stream": "^1.0.0", @@ -3881,18 +2750,16 @@ }, "node_modules/@lerna-lite/version/node_modules/conventional-changelog-preset-loader": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-4.1.0.tgz", - "integrity": "sha512-HozQjJicZTuRhCRTq4rZbefaiCzRM2pr6u2NL3XhrmQm4RMnDXfESU6JKu/pnKwx5xtdkYfNCsbhN5exhiKGJA==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" } }, "node_modules/@lerna-lite/version/node_modules/conventional-changelog-writer": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-7.0.1.tgz", - "integrity": "sha512-Uo+R9neH3r/foIvQ0MKcsXkX642hdm9odUp7TqgFS7BsalTcjzRlIfWZrZR1gbxOozKucaKt5KAbjW8J8xRSmA==", "dev": true, + "license": "MIT", "dependencies": { "conventional-commits-filter": "^4.0.0", "handlebars": "^4.7.7", @@ -3910,18 +2777,16 @@ }, "node_modules/@lerna-lite/version/node_modules/conventional-commits-filter": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-4.0.0.tgz", - "integrity": "sha512-rnpnibcSOdFcdclpFwWa+pPlZJhXE7l+XK04zxhbWrhgpR96h33QLz8hITTXbcYICxVr3HZFtbtUAQ+4LdBo9A==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" } }, "node_modules/@lerna-lite/version/node_modules/conventional-commits-parser": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", - "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", "dev": true, + "license": "MIT", "dependencies": { "is-text-path": "^2.0.0", "JSONStream": "^1.3.5", @@ -3937,9 +2802,8 @@ }, "node_modules/@lerna-lite/version/node_modules/conventional-recommended-bump": { "version": "9.0.0", - "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-9.0.0.tgz", - "integrity": "sha512-HR1yD0G5HgYAu6K0wJjLd7QGRK8MQDqqj6Tn1n/ja1dFwBCE6QmV+iSgQ5F7hkx7OUR/8bHpxJqYtXj2f/opPQ==", "dev": true, + "license": "MIT", "dependencies": { "conventional-changelog-preset-loader": "^4.1.0", "conventional-commits-filter": "^4.0.0", @@ -3957,9 +2821,8 @@ }, "node_modules/@lerna-lite/version/node_modules/dargs": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", - "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -3967,34 +2830,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna-lite/version/node_modules/dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", - "dev": true, - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/@lerna-lite/version/node_modules/detect-indent": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", - "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", - "dev": true, - "engines": { - "node": ">=12.20" - } - }, "node_modules/@lerna-lite/version/node_modules/find-up": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^7.1.0", "path-exists": "^5.0.0" @@ -4006,27 +2845,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna-lite/version/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "node_modules/@lerna-lite/version/node_modules/get-stream": { + "version": "9.0.1", "dev": true, + "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" }, "engines": { - "node": ">=14.14" - } - }, - "node_modules/@lerna-lite/version/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "engines": { - "node": ">=16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4034,9 +2862,8 @@ }, "node_modules/@lerna-lite/version/node_modules/git-raw-commits": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", - "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", "dev": true, + "license": "MIT", "dependencies": { "dargs": "^8.0.0", "meow": "^12.0.1", @@ -4051,9 +2878,8 @@ }, "node_modules/@lerna-lite/version/node_modules/git-semver-tags": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-7.0.1.tgz", - "integrity": "sha512-NY0ZHjJzyyNXHTDZmj+GG7PyuAKtMsyWSwh07CR2hOZFa+/yoTsXci/nF2obzL8UDhakFNkD9gNdt/Ed+cxh2Q==", "dev": true, + "license": "MIT", "dependencies": { "meow": "^12.0.1", "semver": "^7.5.2" @@ -4067,42 +2893,16 @@ }, "node_modules/@lerna-lite/version/node_modules/git-url-parse": { "version": "14.0.0", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-14.0.0.tgz", - "integrity": "sha512-NnLweV+2A4nCvn4U/m2AoYu0pPKlsmhK9cknG7IMwsjFY1S2jxM+mAhsDxyxfCIGfGaD+dozsyX4b6vkYc83yQ==", "dev": true, + "license": "MIT", "dependencies": { "git-up": "^7.0.0" } }, - "node_modules/@lerna-lite/version/node_modules/hosted-git-info": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", - "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", - "dev": true, - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/@lerna-lite/version/node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@lerna-lite/version/node_modules/is-stream": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -4112,9 +2912,8 @@ }, "node_modules/@lerna-lite/version/node_modules/is-text-path": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", - "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", "dev": true, + "license": "MIT", "dependencies": { "text-extensions": "^2.0.0" }, @@ -4124,52 +2923,24 @@ }, "node_modules/@lerna-lite/version/node_modules/json-parse-even-better-errors": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", - "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", "dev": true, + "license": "MIT", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@lerna-lite/version/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/@lerna-lite/version/node_modules/lines-and-columns": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", - "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/@lerna-lite/version/node_modules/load-json-file": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", - "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@lerna-lite/version/node_modules/locate-path": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^6.0.0" }, @@ -4181,15 +2952,11 @@ } }, "node_modules/@lerna-lite/version/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==", + "version": "5.0.0", "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4197,9 +2964,8 @@ }, "node_modules/@lerna-lite/version/node_modules/meow": { "version": "12.1.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", - "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", "dev": true, + "license": "MIT", "engines": { "node": ">=16.10" }, @@ -4208,10 +2974,9 @@ } }, "node_modules/@lerna-lite/version/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.5", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -4224,9 +2989,8 @@ }, "node_modules/@lerna-lite/version/node_modules/node-fetch": { "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "dev": true, + "license": "MIT", "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -4240,43 +3004,26 @@ "url": "https://opencollective.com/node-fetch" } }, - "node_modules/@lerna-lite/version/node_modules/normalize-package-data": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.0.tgz", - "integrity": "sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==", + "node_modules/@lerna-lite/version/node_modules/p-limit": { + "version": "5.0.0", "dev": true, + "license": "MIT", "dependencies": { - "hosted-git-info": "^7.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" + "yocto-queue": "^1.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/@lerna-lite/version/node_modules/npm-package-arg": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", - "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", - "dev": true, - "dependencies": { - "hosted-git-info": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" + "node": ">=18" }, - "engines": { - "node": "^16.14.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna-lite/version/node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "node_modules/@lerna-lite/version/node_modules/p-locate": { + "version": "6.0.0", "dev": true, + "license": "MIT", "dependencies": { - "yocto-queue": "^1.0.0" + "p-limit": "^4.0.0" }, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" @@ -4285,13 +3032,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna-lite/version/node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "node_modules/@lerna-lite/version/node_modules/p-locate/node_modules/p-limit": { + "version": "4.0.0", "dev": true, + "license": "MIT", "dependencies": { - "p-limit": "^4.0.0" + "yocto-queue": "^1.0.0" }, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" @@ -4301,10 +3047,9 @@ } }, "node_modules/@lerna-lite/version/node_modules/p-map": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.1.tgz", - "integrity": "sha512-2wnaR0XL/FDOj+TgpDuRb2KTjLnu3Fma6b1ZUwGY7LcqenMcvP/YFpjpbPKY6WVGsbuJZRuoUz8iPrt8ORnAFw==", + "version": "7.0.2", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -4314,9 +3059,8 @@ }, "node_modules/@lerna-lite/version/node_modules/p-pipe": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-4.0.0.tgz", - "integrity": "sha512-HkPfFklpZQPUKBFXzKFB6ihLriIHxnmuQdK9WmLDwe4hf2PdhhfWT/FJa+pc3bA1ywvKXtedxIRmd4Y7BTXE4w==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -4326,9 +3070,8 @@ }, "node_modules/@lerna-lite/version/node_modules/p-reduce": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-3.0.0.tgz", - "integrity": "sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -4338,9 +3081,8 @@ }, "node_modules/@lerna-lite/version/node_modules/parse-json": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.1.tgz", - "integrity": "sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.21.4", "error-ex": "^1.3.2", @@ -4357,9 +3099,8 @@ }, "node_modules/@lerna-lite/version/node_modules/parse-json/node_modules/type-fest": { "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=14.16" }, @@ -4369,18 +3110,16 @@ }, "node_modules/@lerna-lite/version/node_modules/path-exists": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, "node_modules/@lerna-lite/version/node_modules/pify": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-6.1.0.tgz", - "integrity": "sha512-KocF8ve28eFjjuBKKGvzOBGzG8ew2OqOOSxTTZhirkzH7h3BI1vyzqlR0qbfcDBve1Yzo3FVlWUAtCRrbVN8Fw==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.16" }, @@ -4388,20 +3127,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna-lite/version/node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/@lerna-lite/version/node_modules/read-pkg": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-8.1.0.tgz", - "integrity": "sha512-PORM8AgzXeskHO/WEv312k9U03B8K9JSiWF/8N9sUuFjBa+9SF2u6K7VClzXwDXab51jCd8Nd36CNM+zR97ScQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/normalize-package-data": "^2.4.1", "normalize-package-data": "^6.0.0", @@ -4417,9 +3146,8 @@ }, "node_modules/@lerna-lite/version/node_modules/read-pkg-up": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-10.1.0.tgz", - "integrity": "sha512-aNtBq4jR8NawpKJQldrQcSW9y/d+KWH4v24HWkHljOZ7H0av+YTGANBzRh9A5pw7v/bLVsLVPpOhJ7gHNVy8lA==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^6.3.0", "read-pkg": "^8.1.0", @@ -4432,38 +3160,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna-lite/version/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@lerna-lite/version/node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@lerna-lite/version/node_modules/slash": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.16" }, @@ -4471,44 +3171,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna-lite/version/node_modules/sort-keys": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.0.0.tgz", - "integrity": "sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==", - "dev": true, - "dependencies": { - "is-plain-obj": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@lerna-lite/version/node_modules/split2": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", "dev": true, + "license": "ISC", "engines": { "node": ">= 10.x" } }, - "node_modules/@lerna-lite/version/node_modules/temp-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", - "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", - "dev": true, - "engines": { - "node": ">=14.16" - } - }, "node_modules/@lerna-lite/version/node_modules/text-extensions": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", - "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -4518,9 +3192,8 @@ }, "node_modules/@lerna-lite/version/node_modules/type-fest": { "version": "4.11.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.11.1.tgz", - "integrity": "sha512-MFMf6VkEVZAETidGGSYW2B1MjXbGX+sWIywn2QPEaJ3j08V+MwVRHMXtf2noB8ENJaD0LIun9wh5Z6OPNf1QzQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=16" }, @@ -4529,95 +3202,121 @@ } }, "node_modules/@lerna-lite/version/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "version": "10.0.0", "dev": true, "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, - "node_modules/@lerna-lite/version/node_modules/validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", + "node_modules/@lerna-lite/version/node_modules/yocto-queue": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "builtins": "^5.0.0" + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/are-we-there-yet": { + "version": "2.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/@lerna-lite/version/node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "node_modules/@mapbox/node-pre-gyp/node_modules/gauge": { + "version": "3.0.2", "dev": true, + "license": "ISC", "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@lerna-lite/version/node_modules/write-json-file": { + "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-5.0.0.tgz", - "integrity": "sha512-ddSsCLa4aQ3kI21BthINo4q905/wfhvQ3JL3774AcRjBaiQmfn5v4rw77jQ7T6CmAit9VOQO+FsLyPkwxoB1fw==", "dev": true, + "license": "ISC", "dependencies": { - "detect-indent": "^7.0.0", - "is-plain-obj": "^4.0.0", - "sort-keys": "^5.0.0", - "write-file-atomic": "^3.0.3" + "abbrev": "1" }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "bin": { + "nopt": "bin/nopt.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=6" } }, - "node_modules/@lerna-lite/version/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@lerna-lite/version/node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "node_modules/@mapbox/node-pre-gyp/node_modules/npmlog": { + "version": "5.0.1", "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" } }, - "node_modules/@ljharb/through": { - "version": "2.3.12", - "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.12.tgz", - "integrity": "sha512-ajo/heTlG3QgC8EGP6APIejksVAYt4ayz4tqoP3MolFELzcH1x1fzwEYRJTPO0IELutZ5HQ0c26/GqAYy79u3g==", + "node_modules/@mapbox/node-pre-gyp/node_modules/rimraf": { + "version": "3.0.2", "dev": true, + "license": "ISC", "dependencies": { - "call-bind": "^1.0.5" + "glob": "^7.1.3" }, - "engines": { - "node": ">= 0.4" + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@napi-rs/cli": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.16.2.tgz", - "integrity": "sha512-U2aZfnr0s9KkXpZlYC0l5WxWCXL7vJUNpCnWMwq3T9GG9rhYAAUM9CTZsi1Z+0iR2LcHbfq9EfMgoqnuTyUjfg==", + "version": "2.18.4", "dev": true, + "license": "MIT", "bin": { "napi": "scripts/index.js" }, @@ -4631,8 +3330,7 @@ }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -4643,16 +3341,14 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -4663,8 +3359,7 @@ }, "node_modules/@npmcli/agent": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.1.tgz", - "integrity": "sha512-H4FrOVtNyWC8MUwL3UfjOsAihHvT1Pe8POj3JvjXhSTJipsZMtgUALCT4mGyYZNxymkUfOw3PUj6dE4QPp6osQ==", + "license": "ISC", "dependencies": { "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", @@ -4678,8 +3373,7 @@ }, "node_modules/@npmcli/agent/node_modules/agent-base": { "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "license": "MIT", "dependencies": { "debug": "^4.3.4" }, @@ -4689,8 +3383,7 @@ }, "node_modules/@npmcli/agent/node_modules/http-proxy-agent": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -4701,8 +3394,7 @@ }, "node_modules/@npmcli/agent/node_modules/https-proxy-agent": { "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "license": "MIT", "dependencies": { "agent-base": "^7.0.2", "debug": "4" @@ -4713,8 +3405,7 @@ }, "node_modules/@npmcli/agent/node_modules/socks-proxy-agent": { "version": "8.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", - "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "license": "MIT", "dependencies": { "agent-base": "^7.0.2", "debug": "^4.3.4", @@ -4726,9 +3417,8 @@ }, "node_modules/@npmcli/fs": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.0.tgz", - "integrity": "sha512-VhP1qZLXcrXRIaPoqb4YA55JQxLNF3jNR4T55IdOJa3+IFJKNYHtPvtXx8slmeMavj37vCzCfrqQM1vWLsYKLA==", "dev": true, + "license": "ISC", "dependencies": { "@gar/promisify": "^1.0.1", "semver": "^7.3.5" @@ -4739,8 +3429,7 @@ }, "node_modules/@npmcli/git": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-5.0.4.tgz", - "integrity": "sha512-nr6/WezNzuYUppzXRaYu/W4aT5rLxdXqEFupbh6e/ovlYFQ8hpu1UUPV3Ir/YTl+74iXl2ZOMlGzudh9ZPUchQ==", + "license": "ISC", "dependencies": { "@npmcli/promise-spawn": "^7.0.0", "lru-cache": "^10.0.1", @@ -4755,59 +3444,23 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/@npmcli/git/node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dependencies": { - "semver": "^7.0.0" - } - }, - "node_modules/@npmcli/git/node_modules/hosted-git-info": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", - "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, "node_modules/@npmcli/git/node_modules/isexe": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "license": "ISC", "engines": { "node": ">=16" } }, "node_modules/@npmcli/git/node_modules/npm-normalize-package-bin": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@npmcli/git/node_modules/npm-package-arg": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", - "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", - "dependencies": { - "hosted-git-info": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, "node_modules/@npmcli/git/node_modules/npm-pick-manifest": { "version": "9.0.0", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.0.0.tgz", - "integrity": "sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg==", + "license": "ISC", "dependencies": { "npm-install-checks": "^6.0.0", "npm-normalize-package-bin": "^3.0.0", @@ -4820,27 +3473,14 @@ }, "node_modules/@npmcli/git/node_modules/proc-log": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/git/node_modules/validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", - "dependencies": { - "builtins": "^5.0.0" - }, + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/@npmcli/git/node_modules/which": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "license": "ISC", "dependencies": { "isexe": "^3.1.1" }, @@ -4853,9 +3493,8 @@ }, "node_modules/@npmcli/installed-package-contents": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz", - "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", "dev": true, + "license": "ISC", "dependencies": { "npm-bundled": "^1.1.1", "npm-normalize-package-bin": "^1.0.1" @@ -4869,9 +3508,8 @@ }, "node_modules/@npmcli/map-workspaces": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-2.0.4.tgz", - "integrity": "sha512-bMo0aAfwhVwqoVM5UzX1DJnlvVvzDCHae821jv48L1EsrYwfOZChlqWYXEtto/+BkBXetPbEWgau++/brh4oVg==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/name-from-folder": "^1.0.1", "glob": "^8.0.1", @@ -4884,18 +3522,16 @@ }, "node_modules/@npmcli/map-workspaces/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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/@npmcli/map-workspaces/node_modules/glob": { "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -4912,9 +3548,8 @@ }, "node_modules/@npmcli/map-workspaces/node_modules/minimatch": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -4924,9 +3559,8 @@ }, "node_modules/@npmcli/map-workspaces/node_modules/read-package-json-fast": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", - "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", "dev": true, + "license": "ISC", "dependencies": { "json-parse-even-better-errors": "^2.3.0", "npm-normalize-package-bin": "^1.0.1" @@ -4937,9 +3571,8 @@ }, "node_modules/@npmcli/metavuln-calculator": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-3.1.1.tgz", - "integrity": "sha512-n69ygIaqAedecLeVH3KnO39M6ZHiJ2dEv5A7DGvcqCB8q17BGUgW8QaanIkbWUo2aYGZqJaOORTLAlIvKjNDKA==", "dev": true, + "license": "ISC", "dependencies": { "cacache": "^16.0.0", "json-parse-even-better-errors": "^2.3.1", @@ -4952,9 +3585,8 @@ }, "node_modules/@npmcli/metavuln-calculator/node_modules/@npmcli/git": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-3.0.2.tgz", - "integrity": "sha512-CAcd08y3DWBJqJDpfuVL0uijlq5oaXaOJEKHKc4wqrjd00gkvTZB+nFuLn+doOOKddaQS9JfqtNoFCO2LCvA3w==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/promise-spawn": "^3.0.0", "lru-cache": "^7.4.4", @@ -4972,9 +3604,8 @@ }, "node_modules/@npmcli/metavuln-calculator/node_modules/@npmcli/promise-spawn": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-3.0.0.tgz", - "integrity": "sha512-s9SgS+p3a9Eohe68cSI3fi+hpcZUmXq5P7w0kMlAsWVtR7XbK3ptkZqKT2cK1zLDObJ3sR+8P59sJE0w/KTL1g==", "dev": true, + "license": "ISC", "dependencies": { "infer-owner": "^1.0.4" }, @@ -4984,27 +3615,24 @@ }, "node_modules/@npmcli/metavuln-calculator/node_modules/builtins": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.0.0" } }, "node_modules/@npmcli/metavuln-calculator/node_modules/chownr": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/@npmcli/metavuln-calculator/node_modules/hosted-git-info": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz", - "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^7.5.1" }, @@ -5014,18 +3642,16 @@ }, "node_modules/@npmcli/metavuln-calculator/node_modules/lru-cache": { "version": "7.14.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz", - "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } }, "node_modules/@npmcli/metavuln-calculator/node_modules/minipass-fetch": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", "dev": true, + "license": "MIT", "dependencies": { "minipass": "^3.1.6", "minipass-sized": "^1.0.3", @@ -5040,9 +3666,8 @@ }, "node_modules/@npmcli/metavuln-calculator/node_modules/npm-package-arg": { "version": "9.1.2", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", - "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", "dev": true, + "license": "ISC", "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -5055,9 +3680,8 @@ }, "node_modules/@npmcli/metavuln-calculator/node_modules/npm-registry-fetch": { "version": "13.3.1", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-13.3.1.tgz", - "integrity": "sha512-eukJPi++DKRTjSBRcDZSDDsGqRK3ehbxfFUcgaRd0Yp6kRwOwh2WVn0r+8rMB4nnuzvAk6rQVzl6K5CkYOmnvw==", "dev": true, + "license": "ISC", "dependencies": { "make-fetch-happen": "^10.0.6", "minipass": "^3.1.6", @@ -5073,9 +3697,8 @@ }, "node_modules/@npmcli/metavuln-calculator/node_modules/pacote": { "version": "13.6.2", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-13.6.2.tgz", - "integrity": "sha512-Gu8fU3GsvOPkak2CkbojR7vjs3k3P9cA6uazKTHdsdV0gpCEQq2opelnEv30KRQWgVzP5Vd/5umjcedma3MKtg==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/git": "^3.0.0", "@npmcli/installed-package-contents": "^1.0.7", @@ -5108,9 +3731,8 @@ }, "node_modules/@npmcli/metavuln-calculator/node_modules/read-package-json-fast": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", - "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", "dev": true, + "license": "ISC", "dependencies": { "json-parse-even-better-errors": "^2.3.0", "npm-normalize-package-bin": "^1.0.1" @@ -5121,9 +3743,8 @@ }, "node_modules/@npmcli/metavuln-calculator/node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -5136,9 +3757,8 @@ }, "node_modules/@npmcli/metavuln-calculator/node_modules/validate-npm-package-name": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz", - "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", "dev": true, + "license": "ISC", "dependencies": { "builtins": "^5.0.0" }, @@ -5148,24 +3768,21 @@ }, "node_modules/@npmcli/name-from-folder": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz", - "integrity": "sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@npmcli/node-gyp": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-2.0.0.tgz", - "integrity": "sha512-doNI35wIe3bBaEgrlPfdJPaCpUR89pJWep4Hq3aRdh6gKazIVWfs0jHttvSSoq47ZXgC7h73kDsUl8AoIQUB+A==", "dev": true, + "license": "ISC", "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/@npmcli/package-json": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-2.0.0.tgz", - "integrity": "sha512-42jnZ6yl16GzjWSH7vtrmWyJDGVa/LXPdpN2rcUWolFjc9ON2N3uz0qdBbQACfmhuJZ2lbKYtmK5qx68ZPLHMA==", "dev": true, + "license": "ISC", "dependencies": { "json-parse-even-better-errors": "^2.3.1" }, @@ -5175,8 +3792,7 @@ }, "node_modules/@npmcli/promise-spawn": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.1.tgz", - "integrity": "sha512-P4KkF9jX3y+7yFUxgcUdDtLy+t4OlDGuEBLNs57AZsfSfg+uV6MLndqGpnl4831ggaEdXwR50XFoZP4VFtHolg==", + "license": "ISC", "dependencies": { "which": "^4.0.0" }, @@ -5186,16 +3802,14 @@ }, "node_modules/@npmcli/promise-spawn/node_modules/isexe": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "license": "ISC", "engines": { "node": ">=16" } }, "node_modules/@npmcli/promise-spawn/node_modules/which": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "license": "ISC", "dependencies": { "isexe": "^3.1.1" }, @@ -5206,11 +3820,17 @@ "node": "^16.13.0 || >=18.0.0" } }, + "node_modules/@npmcli/redact": { + "version": "2.0.1", + "license": "ISC", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/@npmcli/run-script": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-4.2.1.tgz", - "integrity": "sha512-7dqywvVudPSrRCW5nTHpHgeWnbBtz8cFkOuKrecm6ih+oO9ciydhWt6OF7HlqupRRmB8Q/gECVdB9LMfToJbRg==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/node-gyp": "^2.0.0", "@npmcli/promise-spawn": "^3.0.0", @@ -5224,9 +3844,8 @@ }, "node_modules/@npmcli/run-script/node_modules/@npmcli/promise-spawn": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-3.0.0.tgz", - "integrity": "sha512-s9SgS+p3a9Eohe68cSI3fi+hpcZUmXq5P7w0kMlAsWVtR7XbK3ptkZqKT2cK1zLDObJ3sR+8P59sJE0w/KTL1g==", "dev": true, + "license": "ISC", "dependencies": { "infer-owner": "^1.0.4" }, @@ -5236,9 +3855,8 @@ }, "node_modules/@npmcli/run-script/node_modules/read-package-json-fast": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", - "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", "dev": true, + "license": "ISC", "dependencies": { "json-parse-even-better-errors": "^2.3.0", "npm-normalize-package-bin": "^1.0.1" @@ -5247,16 +3865,155 @@ "node": ">=10" } }, + "node_modules/@octokit/auth-token": { + "version": "5.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "6.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.0.0", + "@octokit/request": "^9.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.0.0", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "10.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql": { + "version": "8.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/request": "^9.0.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "22.2.0", + "dev": true, + "license": "MIT" + }, "node_modules/@octokit/plugin-enterprise-rest": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz", - "integrity": "sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "11.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.5.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "5.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "13.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.5.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/request": { + "version": "9.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^10.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "6.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest": { + "version": "21.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/core": "^6.1.2", + "@octokit/plugin-paginate-rest": "^11.0.0", + "@octokit/plugin-request-log": "^5.1.0", + "@octokit/plugin-rest-endpoint-methods": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "13.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^22.2.0" + } }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", "optional": true, "engines": { "node": ">=14" @@ -5264,19 +4021,39 @@ }, "node_modules/@popperjs/core": { "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "dev": true, + "license": "MIT", "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" } }, + "node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@shikijs/core": { + "version": "1.10.0", + "dev": true, + "license": "MIT" + }, "node_modules/@sigstore/bundle": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.2.0.tgz", - "integrity": "sha512-5VI58qgNs76RDrwXNhpmyN/jKpq9evV/7f1XrcqcAfvxDl5SeVY/I5Rmfe96ULAV7/FK5dge9RBKGBJPhL1WsQ==", + "license": "Apache-2.0", "dependencies": { "@sigstore/protobuf-specs": "^0.3.0" }, @@ -5286,24 +4063,21 @@ }, "node_modules/@sigstore/core": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-1.0.0.tgz", - "integrity": "sha512-dW2qjbWLRKGu6MIDUTBuJwXCnR8zivcSpf5inUzk7y84zqy/dji0/uahppoIgMoKeR+6pUZucrwHfkQQtiG9Rw==", + "license": "Apache-2.0", "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/@sigstore/protobuf-specs": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.3.0.tgz", - "integrity": "sha512-zxiQ66JFOjVvP9hbhGj/F/qNdsZfkGb/dVXSanNRNuAzMlr4MC95voPUBX8//ZNnmv3uSYzdfR/JSkrgvZTGxA==", + "license": "Apache-2.0", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/@sigstore/sign": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-2.2.3.tgz", - "integrity": "sha512-LqlA+ffyN02yC7RKszCdMTS6bldZnIodiox+IkT8B2f8oRYXCB3LQ9roXeiEL21m64CVH1wyveYAORfD65WoSw==", + "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^2.2.0", "@sigstore/core": "^1.0.0", @@ -5316,8 +4090,7 @@ }, "node_modules/@sigstore/sign/node_modules/@npmcli/fs": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "license": "ISC", "dependencies": { "semver": "^7.3.5" }, @@ -5327,16 +4100,14 @@ }, "node_modules/@sigstore/sign/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==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/@sigstore/sign/node_modules/cacache": { "version": "18.0.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", - "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", + "license": "ISC", "dependencies": { "@npmcli/fs": "^3.1.0", "fs-minipass": "^3.0.0", @@ -5357,8 +4128,7 @@ }, "node_modules/@sigstore/sign/node_modules/fs-minipass": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -5368,8 +4138,7 @@ }, "node_modules/@sigstore/sign/node_modules/glob": { "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^2.3.5", @@ -5389,8 +4158,7 @@ }, "node_modules/@sigstore/sign/node_modules/make-fetch-happen": { "version": "13.0.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", - "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", + "license": "ISC", "dependencies": { "@npmcli/agent": "^2.0.0", "cacache": "^18.0.0", @@ -5410,8 +4178,7 @@ }, "node_modules/@sigstore/sign/node_modules/minimatch": { "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -5424,16 +4191,14 @@ }, "node_modules/@sigstore/sign/node_modules/minipass": { "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/@sigstore/sign/node_modules/minipass-collect": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -5443,8 +4208,7 @@ }, "node_modules/@sigstore/sign/node_modules/minipass-fetch": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "license": "MIT", "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", @@ -5459,8 +4223,7 @@ }, "node_modules/@sigstore/sign/node_modules/ssri": { "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -5470,8 +4233,7 @@ }, "node_modules/@sigstore/sign/node_modules/unique-filename": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "license": "ISC", "dependencies": { "unique-slug": "^4.0.0" }, @@ -5481,8 +4243,7 @@ }, "node_modules/@sigstore/sign/node_modules/unique-slug": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, @@ -5492,8 +4253,7 @@ }, "node_modules/@sigstore/tuf": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-2.3.1.tgz", - "integrity": "sha512-9Iv40z652td/QbV0o5n/x25H9w6IYRt2pIGbTX55yFDYlApDQn/6YZomjz6+KBx69rXHLzHcbtTS586mDdFD+Q==", + "license": "Apache-2.0", "dependencies": { "@sigstore/protobuf-specs": "^0.3.0", "tuf-js": "^2.2.0" @@ -5504,8 +4264,7 @@ }, "node_modules/@sigstore/verify": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-1.1.0.tgz", - "integrity": "sha512-1fTqnqyTBWvV7cftUUFtDcHPdSox0N3Ub7C0lRyReYx4zZUlNTZjCV+HPy4Lre+r45dV7Qx5JLKvqqsgxuyYfg==", + "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^2.2.0", "@sigstore/core": "^1.0.0", @@ -5515,11 +4274,14 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "license": "MIT" + }, "node_modules/@sindresorhus/merge-streams": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -5529,75 +4291,66 @@ }, "node_modules/@sinonjs/commons": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.0" } }, "node_modules/@tootallnate/once": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/@tsconfig/node10": { "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", "dev": true, + "license": "MIT", "optional": true, "peer": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", "dev": true, + "license": "MIT", "optional": true, "peer": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", "dev": true, + "license": "MIT", "optional": true, "peer": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true, + "license": "MIT", "optional": true, "peer": true }, "node_modules/@tufjs/canonical-json": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", - "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", + "license": "MIT", "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/@tufjs/models": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-2.0.0.tgz", - "integrity": "sha512-c8nj8BaOExmZKO2DXhDfegyhSGcG9E/mPN3U13L+/PsoWm1uaGiHHjxqSHQiasDBQwDA3aHuw9+9spYAP1qvvg==", + "license": "MIT", "dependencies": { "@tufjs/canonical-json": "2.0.0", "minimatch": "^9.0.3" @@ -5608,16 +4361,14 @@ }, "node_modules/@tufjs/models/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==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/@tufjs/models/node_modules/minimatch": { "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -5630,9 +4381,8 @@ }, "node_modules/@types/babel__core": { "version": "7.1.19", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", - "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0", @@ -5643,18 +4393,16 @@ }, "node_modules/@types/babel__generator": { "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" @@ -5662,172 +4410,103 @@ }, "node_modules/@types/babel__traverse": { "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.2.tgz", - "integrity": "sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.3.0" } }, "node_modules/@types/cross-spawn": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.3.tgz", - "integrity": "sha512-BDAkU7WHHRHnvBf5z89lcvACsvkz/n7Tv+HyD/uW76O29HoH1Tk/W6iQrepaZVbisvlEek4ygwT8IW7ow9XLAA==", + "version": "6.0.6", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/diff": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.0.2.tgz", - "integrity": "sha512-uw8eYMIReOwstQ0QKF0sICefSy8cNO/v7gOTiIy9SbwuHyEecJUm7qlgueOO5S1udZ5I/irVydHVwMchgzbKTg==", - "dev": true - }, - "node_modules/@types/find-up": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@types/find-up/-/find-up-2.1.1.tgz", - "integrity": "sha512-60LC501bQRN9/3yfVaEEMd7IndaufffL56PBRAejPpUrY304Ps1jfnjNqPw5jmM5R8JHWiKBAe5IHzNcPV41AA==", - "dev": true + "version": "5.2.1", + "dev": true, + "license": "MIT" }, "node_modules/@types/fs-extra": { - "version": "9.0.13", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", - "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "version": "11.0.4", "dev": true, "license": "MIT", "dependencies": { + "@types/jsonfile": "*", "@types/node": "*" } }, "node_modules/@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "version": "8.1.0", "dev": true, + "license": "MIT", "dependencies": { - "@types/minimatch": "*", + "@types/minimatch": "^5.1.2", "@types/node": "*" } }, "node_modules/@types/graceful-fs": { "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", "dev": true, + "license": "MIT", "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "node_modules/@types/istanbul-reports": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", "dev": true, + "license": "MIT", "dependencies": { "@types/istanbul-lib-report": "*" } }, "node_modules/@types/jest": { - "version": "29.5.6", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.6.tgz", - "integrity": "sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w==", + "version": "29.5.12", "dev": true, + "license": "MIT", "dependencies": { "expect": "^29.0.0", "pretty-format": "^29.0.0" } }, - "node_modules/@types/jest/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@types/jest/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@types/jest/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@types/jest/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@types/jest/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/@types/jquery": { "version": "3.5.30", "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.30.tgz", "integrity": "sha512-nbWKkkyb919DOUxjmRVk8vwtDb0/k8FKncmUKFi+NY+QXqWltooxTrswvz4LspQwxvLdvzBN1TImr6cw3aQx2A==", "dev": true, + "license": "MIT", "dependencies": { "@types/sizzle": "*" } }, "node_modules/@types/js-yaml": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", - "integrity": "sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==", - "dev": true + "version": "4.0.9", + "dev": true, + "license": "MIT" }, "node_modules/@types/json-schema": { "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/jsonfile": { "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", - "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5839,70 +4518,65 @@ "resolved": "https://registry.npmjs.org/@types/jstree/-/jstree-3.3.46.tgz", "integrity": "sha512-Xj+lbRetEsI1TkP2cmQuCDSCT7qD3OUUCtok/8q2f2hx4PCXkBdjRO7AnS8CNj/tKsqjjZ0Pq6cNfyRcqDumsw==", "dev": true, + "license": "MIT", "dependencies": { "@types/jquery": "*" } }, "node_modules/@types/lodash": { - "version": "4.14.178", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz", - "integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==", - "dev": true + "version": "4.17.6", + "dev": true, + "license": "MIT" }, "node_modules/@types/lodash-deep": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/lodash-deep/-/lodash-deep-2.0.2.tgz", - "integrity": "sha512-q/9X4upLiTPmepS9JSYvjcWXWVZtqP/G4bFz9/JHEVR9MmNQhYn9+d9a4SDa2kzFNGzkG5O8vXJlbeWFN0a0kQ==", + "version": "2.0.4", "dev": true, + "license": "MIT", "dependencies": { "@types/lodash": "*" } }, "node_modules/@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", - "dev": true + "version": "5.1.2", + "dev": true, + "license": "MIT" }, "node_modules/@types/mustache": { - "version": "0.8.32", - "resolved": "https://registry.npmjs.org/@types/mustache/-/mustache-0.8.32.tgz", - "integrity": "sha512-RTVWV485OOf4+nO2+feurk0chzHkSjkjALiejpHltyuMf/13fGymbbNNFrSKdSSUg1TIwzszXdWsVirxgqYiFA==", - "dev": true + "version": "4.2.5", + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { - "version": "14.18.63", - "resolved": "https://zowe.jfrog.io/zowe/api/npm/npm-release/@types/node/-/node-14.18.63.tgz", - "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", - "dev": true + "version": "18.19.33", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/node-fetch": { "version": "2.6.11", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "form-data": "^4.0.0" } }, "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true + "version": "2.4.4", + "dev": true, + "license": "MIT" }, "node_modules/@types/npm-package-arg": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@types/npm-package-arg/-/npm-package-arg-6.1.2.tgz", - "integrity": "sha512-K7TdZq7dTZKKgxaFGLR6VPAeNMDM7GwTELlVNyzQ0KKc6Du3+SYYRXFNEDrsCptpEpMjMNKVlb/5/ZNS/MeHjw==", - "dev": true + "version": "6.1.4", + "dev": true, + "license": "MIT" }, "node_modules/@types/npm-registry-fetch": { "version": "8.0.7", - "resolved": "https://registry.npmjs.org/@types/npm-registry-fetch/-/npm-registry-fetch-8.0.7.tgz", - "integrity": "sha512-db9iBh7kDDg4lRT4k4XZ6IiecTEgFCID4qk+VDVPbtzU855q3KZLCn08ATr4H27ntRJVhulQ7GWjl24H42x96w==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "@types/node-fetch": "*", @@ -5913,18 +4587,16 @@ }, "node_modules/@types/npmlog": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@types/npmlog/-/npmlog-7.0.0.tgz", - "integrity": "sha512-hJWbrKFvxKyWwSUXjZMYTINsSOY6IclhvGOZ97M8ac2tmR9hMwmTnYaMdpGhvju9ctWLTPhCS+eLfQNluiEjQQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/pacote": { "version": "11.1.8", - "resolved": "https://registry.npmjs.org/@types/pacote/-/pacote-11.1.8.tgz", - "integrity": "sha512-/XLR0VoTh2JEO0jJg1q/e6Rh9bxjBq9vorJuQmtT7rRrXSiWz7e7NsvXVYJQ0i8JxMlBMPPYDTnrRe7MZRFA8Q==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "@types/npm-registry-fetch": "*", @@ -5933,132 +4605,112 @@ } }, "node_modules/@types/progress": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/progress/-/progress-2.0.5.tgz", - "integrity": "sha512-ZYYVc/kSMkhH9W/4dNK/sLNra3cnkfT2nJyOAIDY+C2u6w72wa0s1aXAezVtbTsnN8HID1uhXCrLwDE2ZXpplg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/readline-sync": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/@types/readline-sync/-/readline-sync-1.4.5.tgz", - "integrity": "sha512-vD/LCH84gWf9CoJaqGL8Ey0/oFrgHNEf/R/SPzoDeZa5Zr8Fh5tPCaTF2UC/m1shAcAHVHHZmDQrsoWMkCj0gA==", - "dev": true - }, - "node_modules/@types/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ==", + "version": "2.0.7", "dev": true, + "license": "MIT", "dependencies": { - "@types/glob": "*", "@types/node": "*" } }, "node_modules/@types/semver": { "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/sizzle": { "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.4.tgz", - "integrity": "sha512-jA2llq2zNkg8HrALI7DtWzhALcVH0l7i89yhY3iBdOz6cBPeACoFq+fkQrjHA39t1hnSFOboZ7A/AY5MMZSlag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/ssh2": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.11.6.tgz", - "integrity": "sha512-8Mf6bhzYYBLEB/G6COux7DS/F5bCWwojv/qFo2yH/e4cLzAavJnxvFXrYW59iKfXdhG6OmzJcXDasgOb/s0rxw==", + "version": "1.15.0", "dev": true, + "license": "MIT", "dependencies": { - "@types/node": "*" + "@types/node": "^18.11.18" } }, "node_modules/@types/ssri": { "version": "7.1.5", - "resolved": "https://registry.npmjs.org/@types/ssri/-/ssri-7.1.5.tgz", - "integrity": "sha512-odD/56S3B51liILSk5aXJlnYt99S6Rt9EFDDqGtJM26rKHApHcwyU/UoYHrzKkdkHMAIquGWCuHtQTbes+FRQw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/stack-trace": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/stack-trace/-/stack-trace-0.0.29.tgz", - "integrity": "sha512-TgfOX+mGY/NyNxJLIbDWrO9DjGoVSW9+aB8H2yy1fy32jsvxijhmyJI9fDFgvz3YP4lvJaq9DzdR/M1bOgVc9g==", - "dev": true + "version": "0.0.33", + "dev": true, + "license": "MIT" }, "node_modules/@types/stack-utils": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/tar": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/@types/tar/-/tar-6.1.3.tgz", - "integrity": "sha512-YzDOr5kdAeqS8dcO6NTTHTMJ44MUCBDoLEIyPtwEn7PssKqUYL49R1iCVJPeiPzPlKi6DbH33eZkpeJ27e4vHg==", + "version": "6.1.13", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", - "minipass": "^3.3.5" + "minipass": "^4.0.0" + } + }, + "node_modules/@types/tar/node_modules/minipass": { + "version": "4.2.8", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" } }, "node_modules/@types/uuid": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", - "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", - "dev": true + "version": "10.0.0", + "dev": true, + "license": "MIT" }, "node_modules/@types/which": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/which/-/which-2.0.1.tgz", - "integrity": "sha512-Jjakcv8Roqtio6w1gr0D7y6twbhx6gGgFGF5BLwajPpnOIOxFkakFhCq+LmyyeAz7BX6ULrjBOxdKaCDy+4+dQ==", - "dev": true + "version": "3.0.4", + "dev": true, + "license": "MIT" }, "node_modules/@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", + "version": "17.0.32", + "license": "MIT", "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { "version": "20.2.1", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", - "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==" + "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.1.tgz", - "integrity": "sha512-FsWboKkWdytGiXT5O1/R9j37YgcjO8MKHSUmWnIEjVaz0krHkplPnYi7mwdb+5+cs0toFNQb0HIrN7zONdIEWg==", + "version": "7.15.0", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "5.40.1", - "@typescript-eslint/type-utils": "5.40.1", - "@typescript-eslint/utils": "5.40.1", - "debug": "^4.3.4", - "ignore": "^5.2.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.15.0", + "@typescript-eslint/type-utils": "7.15.0", + "@typescript-eslint/utils": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -6067,25 +4719,25 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.40.1.tgz", - "integrity": "sha512-IK6x55va5w4YvXd4b3VrXQPldV9vQTxi5ov+g4pMANsXPTXOcfjx08CRR1Dfrcc51syPtXHF5bgLlMHYFrvQtg==", + "version": "7.15.0", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "5.40.1", - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/typescript-estree": "5.40.1", + "@typescript-eslint/scope-manager": "7.15.0", + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/typescript-estree": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0", "debug": "^4.3.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -6093,395 +4745,199 @@ } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.1.tgz", - "integrity": "sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.15.0", "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz", - "integrity": "sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA==", + "node_modules/@typescript-eslint/type-utils": { + "version": "7.15.0", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/visitor-keys": "5.40.1", + "@typescript-eslint/typescript-estree": "7.15.0", + "@typescript-eslint/utils": "7.15.0", "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, + "peerDependencies": { + "eslint": "^8.56.0" + }, "peerDependenciesMeta": { "typescript": { "optional": true } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz", - "integrity": "sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw==", + "node_modules/@typescript-eslint/types": { + "version": "7.15.0", "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.40.1", - "eslint-visitor-keys": "^3.3.0" - }, + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.40.1.tgz", - "integrity": "sha512-jkn4xsJiUQucI16OLCXrLRXDZ3afKhOIqXs4R3O+M00hdQLKR58WuyXPZZjhKLFCEP2g+TXdBRtLQ33UfAdRUg==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.15.0", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/visitor-keys": "5.40.1" + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/visitor-keys": "7.15.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.1.tgz", - "integrity": "sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" } }, - "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz", - "integrity": "sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", "dev": true, + "license": "ISC", "dependencies": { - "@typescript-eslint/types": "5.40.1", - "eslint-visitor-keys": "^3.3.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/scope-manager/node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.40.1.tgz", - "integrity": "sha512-DLAs+AHQOe6n5LRraXiv27IYPhleF0ldEmx6yBqBgBLaNRKTkffhV1RPsjoJBhVup2zHxfaRtan8/YRBgYhU9Q==", + "node_modules/@typescript-eslint/utils": { + "version": "7.15.0", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "5.40.1", - "@typescript-eslint/utils": "5.40.1", - "debug": "^4.3.4", - "tsutils": "^3.21.0" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.15.0", + "@typescript-eslint/types": "7.15.0", + "@typescript-eslint/typescript-estree": "7.15.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.56.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.1.tgz", - "integrity": "sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.15.0", "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "7.15.0", + "eslint-visitor-keys": "^3.4.3" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz", - "integrity": "sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA==", + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "dev": true, + "license": "ISC" + }, + "node_modules/@vercel/nft": { + "version": "0.26.5", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/visitor-keys": "5.40.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "@mapbox/node-pre-gyp": "^1.0.5", + "@rollup/pluginutils": "^4.0.0", + "acorn": "^8.6.0", + "acorn-import-attributes": "^1.9.2", + "async-sema": "^3.1.1", + "bindings": "^1.4.0", + "estree-walker": "2.0.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.2", + "node-gyp-build": "^4.2.2", + "resolve-from": "^5.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "bin": { + "nft": "out/cli.js" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": ">=16" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz", - "integrity": "sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw==", + "node_modules/@zkochan/rimraf": { + "version": "2.1.3", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.40.1", - "eslint-visitor-keys": "^3.3.0" + "rimraf": "^3.0.2" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=12.10" + } + }, + "node_modules/@zkochan/rimraf/node_modules/rimraf": { + "version": "3.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", - "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz", - "integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/visitor-keys": "4.33.0", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.40.1.tgz", - "integrity": "sha512-a2TAVScoX9fjryNrW6BZRnreDUszxqm9eQ9Esv8n5nXApMW0zeANUYlwh/DED04SC/ifuBvXgZpIK5xeJHQ3aw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.40.1", - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/typescript-estree": "5.40.1", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.1.tgz", - "integrity": "sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz", - "integrity": "sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/visitor-keys": "5.40.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz", - "integrity": "sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.40.1", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", - "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.33.0", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@zkochan/rimraf": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@zkochan/rimraf/-/rimraf-2.1.2.tgz", - "integrity": "sha512-Lc2oK51J6aQWcLWTloobJun5ZF41BbTDdLvE+aMcexoVWFoFqvZmnZoyXR2IZk6NJEVoZW8tjgtvQLfTsmRs2Q==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=12.10" - } - }, - "node_modules/@zkochan/rimraf/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@zowe/cli": { @@ -6542,15 +4998,13 @@ }, "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 + "dev": true, + "license": "ISC" }, "node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "version": "8.11.3", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -6558,35 +5012,39 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.2", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/add-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", - "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/agent-base": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, + "license": "MIT", "dependencies": { "debug": "4" }, @@ -6596,9 +5054,8 @@ }, "node_modules/agentkeepalive": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", - "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.1.0", "depd": "^1.1.2", @@ -6610,8 +5067,7 @@ }, "node_modules/aggregate-error": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -6622,9 +5078,8 @@ }, "node_modules/ajv": { "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -6637,19 +5092,17 @@ } }, "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==", + "version": "4.1.3", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/ansi-escapes": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.21.3" }, @@ -6662,9 +5115,8 @@ }, "node_modules/ansi-escapes/node_modules/type-fest": { "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -6672,37 +5124,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "dependencies": { - "ansi-wrap": "0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ansi-parser": { "version": "3.2.10", - "resolved": "https://registry.npmjs.org/ansi-parser/-/ansi-parser-3.2.10.tgz", - "integrity": "sha512-CGKGIbd678lm15IXJXI1cTyOVAnMQw0jES+klW/yIc+GzYccsYanLMhczPIIj2hE64B79g75QfiuWrEWd6nJdg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, + "version": "6.0.1", + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "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==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -6713,20 +5152,15 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "node_modules/any-promise": { + "version": "1.3.0", "dev": true, - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, "node_modules/anymatch": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -6737,104 +5171,96 @@ }, "node_modules/app-module-path": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz", - "integrity": "sha1-ZBqlXft9am8KgUHEucCqULbCTdU=", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/aproba": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true - }, - "node_modules/are-we-there-yet": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-4.0.2.tgz", - "integrity": "sha512-ncSWAawFhKMJDTdoAeOV+jyW1VCMj5QIAwULIBV0SSR7B/RLPPEQiknKcg/RIIZlUQrxELpsxMiTUoAQ4sIUyg==", "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "license": "ISC" }, "node_modules/arg": { "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true, + "license": "MIT", "optional": true, "peer": true }, "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==" + "license": "Python-2.0" + }, + "node_modules/array-differ": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/array-find-index": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/array-ify": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/array-timsort": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", - "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==" + "license": "MIT" }, "node_modules/array-union": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/arrgv": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arrgv/-/arrgv-1.0.2.tgz", - "integrity": "sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.0.0" } }, "node_modules/arrify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/asap": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/asn1": { "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "license": "MIT", "dependencies": { "safer-buffer": "~2.1.0" } }, "node_modules/ast-module-types": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/ast-module-types/-/ast-module-types-2.7.1.tgz", - "integrity": "sha512-Rnnx/4Dus6fn7fTqdeLEAn5vUll5w7/vts0RN608yFa6si/rDOUonlIIiwugHBFWjylHjxm9owoSZn71KwG4gw==", - "dev": true + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } }, "node_modules/async": { "version": "2.6.4", @@ -6846,78 +5272,67 @@ "lodash": "^4.17.14" } }, + "node_modules/async-sema": { + "version": "3.1.1", + "dev": true, + "license": "MIT" + }, "node_modules/asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "license": "ISC", - "engines": { - "node": ">= 4.0.0" - } + "dev": true, + "license": "MIT" }, "node_modules/ava": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/ava/-/ava-4.3.3.tgz", - "integrity": "sha512-9Egq/d9R74ExrWohHeqUlexjDbgZJX5jA1Wq4KCTqc3wIfpGEK79zVy4rBtofJ9YKIxs4PzhJ8BgbW5PlAYe6w==", + "version": "6.1.3", "dev": true, + "license": "MIT", "dependencies": { - "acorn": "^8.7.1", - "acorn-walk": "^8.2.0", - "ansi-styles": "^6.1.0", + "@vercel/nft": "^0.26.2", + "acorn": "^8.11.3", + "acorn-walk": "^8.3.2", + "ansi-styles": "^6.2.1", "arrgv": "^1.0.2", "arrify": "^3.0.0", - "callsites": "^4.0.0", - "cbor": "^8.1.0", - "chalk": "^5.0.1", - "chokidar": "^3.5.3", + "callsites": "^4.1.0", + "cbor": "^9.0.1", + "chalk": "^5.3.0", "chunkd": "^2.0.1", - "ci-info": "^3.3.1", + "ci-info": "^4.0.0", "ci-parallel-vars": "^1.0.1", - "clean-yaml-object": "^0.1.0", - "cli-truncate": "^3.1.0", + "cli-truncate": "^4.0.0", "code-excerpt": "^4.0.0", "common-path-prefix": "^3.0.0", "concordance": "^5.0.4", "currently-unhandled": "^0.4.1", "debug": "^4.3.4", - "del": "^6.1.1", - "emittery": "^0.11.0", - "figures": "^4.0.1", - "globby": "^13.1.1", + "emittery": "^1.0.1", + "figures": "^6.0.1", + "globby": "^14.0.0", "ignore-by-default": "^2.1.0", "indent-string": "^5.0.0", - "is-error": "^2.2.2", "is-plain-object": "^5.0.0", "is-promise": "^4.0.0", "matcher": "^5.0.0", - "mem": "^9.0.2", + "memoize": "^10.0.0", "ms": "^2.1.3", - "p-event": "^5.0.1", - "p-map": "^5.4.0", - "picomatch": "^2.3.1", - "pkg-conf": "^4.0.0", + "p-map": "^7.0.1", + "package-config": "^5.0.0", + "picomatch": "^3.0.1", "plur": "^5.1.0", - "pretty-ms": "^7.0.1", + "pretty-ms": "^9.0.0", "resolve-cwd": "^3.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.5", - "strip-ansi": "^7.0.1", + "stack-utils": "^2.0.6", + "strip-ansi": "^7.1.0", "supertap": "^3.0.1", - "temp-dir": "^2.0.0", - "write-file-atomic": "^4.0.1", - "yargs": "^17.5.1" + "temp-dir": "^3.0.0", + "write-file-atomic": "^5.0.1", + "yargs": "^17.7.2" }, "bin": { "ava": "entrypoints/cli.mjs" }, "engines": { - "node": ">=12.22 <13 || >=14.17 <15 || >=16.4 <17 || >=18" + "node": "^18.18 || ^20.8 || ^21 || ^22" }, "peerDependencies": { "@ava/typescript": "*" @@ -6928,212 +5343,150 @@ } } }, - "node_modules/ava/node_modules/aggregate-error": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", - "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "node_modules/ava/node_modules/ansi-styles": { + "version": "6.2.1", "dev": true, - "dependencies": { - "clean-stack": "^4.0.0", - "indent-string": "^5.0.0" - }, + "license": "MIT", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ava/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ava/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "node_modules/ava/node_modules/arrify": { + "version": "3.0.0", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ava/node_modules/arrify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-3.0.0.tgz", - "integrity": "sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==", + "node_modules/ava/node_modules/chalk": { + "version": "5.3.0", "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/ava/node_modules/callsites": { + "node_modules/ava/node_modules/ci-info": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-4.0.0.tgz", - "integrity": "sha512-y3jRROutgpKdz5vzEhWM34TidDU8vkJppF8dszITeb1PQmSqV3DTxyV8G/lyO/DNvtE1YTedehmw9MPZsCBHxQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/ava/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "node_modules/ava/node_modules/emittery": { + "version": "1.0.3", "dev": true, + "license": "MIT", "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": ">=14.16" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/ava/node_modules/clean-stack": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", - "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "node_modules/ava/node_modules/figures": { + "version": "6.1.0", "dev": true, + "license": "MIT", "dependencies": { - "escape-string-regexp": "5.0.0" + "is-unicode-supported": "^2.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ava/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==", + "node_modules/ava/node_modules/globby": { + "version": "14.0.1", "dev": true, + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" }, "engines": { - "node": ">=12" - } - }, - "node_modules/ava/node_modules/cliui/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/ava/node_modules/cliui/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" + "node": ">=18" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ava/node_modules/emittery": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.11.0.tgz", - "integrity": "sha512-S/7tzL6v5i+4iJd627Nhv9cLFIo5weAIlGccqJFpnBoDB8U1TF2k5tez4J/QNuxyyhWuFqHg1L84Kd3m7iXg6g==", + "node_modules/ava/node_modules/indent-string": { + "version": "5.0.0", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ava/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "node_modules/ava/node_modules/is-unicode-supported": { + "version": "2.0.0", "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ava/node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "node_modules/ava/node_modules/ms": { + "version": "2.1.3", "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } + "license": "MIT" }, - "node_modules/ava/node_modules/figures": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/figures/-/figures-4.0.1.tgz", - "integrity": "sha512-rElJwkA/xS04Vfg+CaZodpso7VqBknOYbzi6I76hI4X80RUjkSxO2oAyPmGbuXUppywjqndOrQDl817hDnI++w==", + "node_modules/ava/node_modules/p-map": { + "version": "7.0.2", "dev": true, - "dependencies": { - "escape-string-regexp": "^5.0.0", - "is-unicode-supported": "^1.2.0" - }, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ava/node_modules/globby": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "node_modules/ava/node_modules/parse-ms": { + "version": "4.0.0", "dev": true, - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", - "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ava/node_modules/globby/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "node_modules/ava/node_modules/path-type": { + "version": "5.0.0", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -7141,46 +5494,48 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ava/node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "node_modules/ava/node_modules/picomatch": { + "version": "3.0.1", "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/ava/node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "node_modules/ava/node_modules/pretty-ms": { + "version": "9.0.0", "dev": true, + "license": "MIT", + "dependencies": { + "parse-ms": "^4.0.0" + }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ava/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/ava/node_modules/p-map": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-5.5.0.tgz", - "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", + "node_modules/ava/node_modules/signal-exit": { + "version": "4.1.0", "dev": true, - "dependencies": { - "aggregate-error": "^4.0.0" + "license": "ISC", + "engines": { + "node": ">=14" }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ava/node_modules/slash": { + "version": "5.1.0", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -7188,9 +5543,8 @@ }, "node_modules/ava/node_modules/strip-ansi": { "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -7201,56 +5555,22 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/ava/node_modules/temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ava/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/ava/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "node_modules/ava/node_modules/write-file-atomic": { + "version": "5.0.1", "dev": true, + "license": "ISC", "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" + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">=12" - } - }, - "node_modules/ava/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": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/babel-jest": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", @@ -7269,9 +5589,8 @@ }, "node_modules/babel-jest/node_modules/@jest/transform": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", @@ -7295,15 +5614,13 @@ }, "node_modules/babel-jest/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 + "dev": true, + "license": "MIT" }, "node_modules/babel-jest/node_modules/jest-haste-map": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", @@ -7326,18 +5643,16 @@ }, "node_modules/babel-jest/node_modules/jest-regex-util": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/babel-jest/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -7352,9 +5667,8 @@ }, "node_modules/babel-jest/node_modules/jest-worker": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", @@ -7367,9 +5681,8 @@ }, "node_modules/babel-jest/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, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -7382,9 +5695,8 @@ }, "node_modules/babel-plugin-istanbul": { "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", @@ -7398,9 +5710,8 @@ }, "node_modules/babel-plugin-jest-hoist": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", @@ -7413,9 +5724,8 @@ }, "node_modules/babel-preset-current-node-syntax": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", @@ -7436,9 +5746,8 @@ }, "node_modules/babel-preset-jest": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, + "license": "MIT", "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" @@ -7452,19 +5761,15 @@ }, "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==" + "license": "MIT" }, "node_modules/balloon-css": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/balloon-css/-/balloon-css-1.2.0.tgz", - "integrity": "sha512-urXwkHgwp6GsXVF+it01485Z2Cj4pnW02ICnM0TemOlkKmCNnDLmyy+ZZiRXBpwldUXO+aRNr7Hdia4CBvXJ5A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true, "funding": [ { @@ -7479,7 +5784,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/basic-auth": { "version": "2.0.1", @@ -7496,23 +5802,20 @@ }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "license": "BSD-3-Clause", "dependencies": { "tweetnacl": "^0.14.3" } }, "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true + "version": "3.0.2", + "dev": true, + "license": "Apache-2.0" }, "node_modules/better-path-resolve": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz", - "integrity": "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==", "dev": true, + "license": "MIT", "dependencies": { "is-windows": "^1.0.0" }, @@ -7522,9 +5825,8 @@ }, "node_modules/bin-links": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-3.0.3.tgz", - "integrity": "sha512-zKdnMPWEdh4F5INR07/eBrodC7QrF5JKvqskjz/ZZRXg5YSAZIbn8zGhbhUrElzHBZ2fvEQdOU59RHcTG3GiwA==", "dev": true, + "license": "ISC", "dependencies": { "cmd-shim": "^5.0.0", "mkdirp-infer-owner": "^2.0.0", @@ -7539,18 +5841,16 @@ }, "node_modules/bin-links/node_modules/npm-normalize-package-bin": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", - "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", "dev": true, + "license": "ISC", "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/bin-links/node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -7561,45 +5861,28 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "node_modules/bindings": { + "version": "1.5.0", "dev": true, - "engines": { - "node": ">=8" + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" } }, "node_modules/bl": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, + "license": "MIT", "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, - "node_modules/bl/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==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/blueimp-md5": { "version": "2.19.0", - "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", - "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/bootstrap": { "version": "5.3.3", @@ -7616,14 +5899,15 @@ "url": "https://opencollective.com/bootstrap" } ], + "license": "MIT", "peerDependencies": { "@popperjs/core": "^2.11.8" } }, "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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7631,8 +5915,7 @@ }, "node_modules/braces": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -7642,8 +5925,6 @@ }, "node_modules/browserslist": { "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "funding": [ { @@ -7659,6 +5940,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "caniuse-lite": "^1.0.30001587", "electron-to-chromium": "^1.4.668", @@ -7674,9 +5956,8 @@ }, "node_modules/bs-logger": { "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", "dev": true, + "license": "MIT", "dependencies": { "fast-json-stable-stringify": "2.x" }, @@ -7686,17 +5967,14 @@ }, "node_modules/bser": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "node-int64": "^0.4.0" } }, "node_modules/buffer": { "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, "funding": [ { @@ -7712,6 +5990,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -7719,14 +5998,11 @@ }, "node_modules/buffer-from": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, + "dev": true, + "license": "MIT" + }, "node_modules/buildcheck": { "version": "0.0.6", - "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz", - "integrity": "sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==", "optional": true, "engines": { "node": ">=10.0.0" @@ -7734,9 +6010,8 @@ }, "node_modules/cacache": { "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/fs": "^2.1.0", "@npmcli/move-file": "^2.0.0", @@ -7763,9 +6038,8 @@ }, "node_modules/cacache/node_modules/@npmcli/fs": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", "dev": true, + "license": "ISC", "dependencies": { "@gar/promisify": "^1.1.3", "semver": "^7.3.5" @@ -7776,9 +6050,8 @@ }, "node_modules/cacache/node_modules/@npmcli/move-file": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", "dev": true, + "license": "MIT", "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" @@ -7789,27 +6062,24 @@ }, "node_modules/cacache/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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/cacache/node_modules/chownr": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/cacache/node_modules/glob": { "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -7826,18 +6096,16 @@ }, "node_modules/cacache/node_modules/lru-cache": { "version": "7.14.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz", - "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } }, "node_modules/cacache/node_modules/minimatch": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -7847,9 +6115,8 @@ }, "node_modules/cacache/node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -7862,9 +6129,8 @@ }, "node_modules/cacache/node_modules/rimraf/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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7872,9 +6138,8 @@ }, "node_modules/cacache/node_modules/rimraf/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, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -7892,9 +6157,8 @@ }, "node_modules/cacache/node_modules/rimraf/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, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -7904,9 +6168,8 @@ }, "node_modules/cacache/node_modules/unique-filename": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", "dev": true, + "license": "ISC", "dependencies": { "unique-slug": "^3.0.0" }, @@ -7916,9 +6179,8 @@ }, "node_modules/cacache/node_modules/unique-slug": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, @@ -7931,6 +6193,7 @@ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -7945,18 +6208,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/camelcase": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { "version": "1.0.30001594", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001594.tgz", - "integrity": "sha512-VblSX6nYqyJVs8DKFMldE2IVCJjZ225LW00ydtUWwh5hk9IfkTOffO6r8gJNsH0qqqeAF8KrbMYA2VEwTlGW5g==", "dev": true, "funding": [ { @@ -7971,24 +6243,23 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/cbor": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", - "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", + "version": "9.0.2", "dev": true, + "license": "MIT", "dependencies": { "nofilter": "^3.1.0" }, "engines": { - "node": ">=12.19" + "node": ">=16" } }, "node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -8002,24 +6273,21 @@ }, "node_modules/char-regex": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/chardet": { "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/chart.js": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.3.tgz", - "integrity": "sha512-qK1gkGSRYcJzqrrzdR6a+I0vQ4/R+SoODXyAjscQ/4mzuNzySaMCd+hyVxitSY1+L2fjPD1Gbn+ibNqRmwQeLw==", + "version": "4.4.2", "dev": true, + "license": "MIT", "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -8027,79 +6295,37 @@ "pnpm": ">=8" } }, - "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/chunkd": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chunkd/-/chunkd-2.0.1.tgz", - "integrity": "sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ci-info": { "version": "3.5.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", - "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ci-parallel-vars": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ci-parallel-vars/-/ci-parallel-vars-1.0.1.tgz", - "integrity": "sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cjs-module-lexer": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/clean-stack": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/clean-yaml-object": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz", - "integrity": "sha512-3yONmlN9CSAkzNwnRCiJQ7Q2xK5mWuEfL3PuTZcAUzhObbXsfsnMptJzXwz93nc5zn9V9TwCVMmV7w4xsm43dw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/cli-cursor": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, + "license": "MIT", "dependencies": { "restore-cursor": "^3.1.0" }, @@ -8109,9 +6335,8 @@ }, "node_modules/cli-spinners": { "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -8120,9 +6345,8 @@ } }, "node_modules/cli-table3": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz", - "integrity": "sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==", + "version": "0.6.5", + "license": "MIT", "dependencies": { "string-width": "^4.2.0" }, @@ -8134,51 +6358,36 @@ } }, "node_modules/cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "version": "4.0.0", "dev": true, + "license": "MIT", "dependencies": { "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" + "string-width": "^7.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "version": "10.3.0", + "dev": true, + "license": "MIT" }, "node_modules/cli-truncate/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "version": "7.1.0", "dev": true, + "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -8186,9 +6395,8 @@ }, "node_modules/cli-truncate/node_modules/strip-ansi": { "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -8199,11 +6407,18 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/cli-width": { + "version": "4.1.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, "node_modules/clipboard": { "version": "2.0.11", - "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", - "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", "dev": true, + "license": "MIT", "dependencies": { "good-listener": "^1.2.2", "select": "^1.1.2", @@ -8212,8 +6427,8 @@ }, "node_modules/cliui": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -8222,8 +6437,8 @@ }, "node_modules/cliui/node_modules/wrap-ansi": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -8235,9 +6450,8 @@ }, "node_modules/clone-deep": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dev": true, + "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", @@ -8249,9 +6463,8 @@ }, "node_modules/clone-deep/node_modules/is-plain-object": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, + "license": "MIT", "dependencies": { "isobject": "^3.0.1" }, @@ -8259,20 +6472,10 @@ "node": ">=0.10.0" } }, - "node_modules/clone-deep/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/cmd-shim": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-5.0.0.tgz", - "integrity": "sha512-qkCtZ59BidfEwHltnJwkyVZn+XQojdAySM1D1gSeh11Z4pW1Kpolkyo53L5noc0nrxmIvyFwTmJRo4xs7FFLPw==", "dev": true, + "license": "ISC", "dependencies": { "mkdirp-infer-owner": "^2.0.0" }, @@ -8282,9 +6485,8 @@ }, "node_modules/co": { "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, + "license": "MIT", "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" @@ -8292,9 +6494,8 @@ }, "node_modules/code-excerpt": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", - "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", "dev": true, + "license": "MIT", "dependencies": { "convert-to-spaces": "^2.0.1" }, @@ -8304,14 +6505,12 @@ }, "node_modules/collect-v8-coverage": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -8321,31 +6520,27 @@ }, "node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "license": "MIT" }, "node_modules/color-support": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true, + "license": "ISC", "bin": { "color-support": "bin.js" } }, "node_modules/colors": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "license": "MIT", "engines": { "node": ">=0.1.90" } }, "node_modules/columnify": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", - "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", "dev": true, + "license": "MIT", "dependencies": { "strip-ansi": "^6.0.1", "wcwidth": "^1.0.0" @@ -8356,9 +6551,8 @@ }, "node_modules/combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -8368,19 +6562,17 @@ }, "node_modules/commander": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/comment-json": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.1.1.tgz", - "integrity": "sha512-v8gmtPvxhBlhdRBLwdHSjGy9BgA23t9H1FctdQKyUrErPjSrJcdDMqBq9B4Irtm7w3TNYLQJNH6ARKnpyag1sA==", + "version": "4.2.3", + "license": "MIT", "dependencies": { "array-timsort": "^1.0.3", - "core-util-is": "^1.0.2", + "core-util-is": "^1.0.3", "esprima": "^4.0.1", "has-own-prop": "^2.0.0", "repeat-string": "^1.6.1" @@ -8391,27 +6583,23 @@ }, "node_modules/common-ancestor-path": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", - "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/common-path-prefix": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/commondir": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/compare-func": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", "dev": true, + "license": "MIT", "dependencies": { "array-ify": "^1.0.0", "dot-prop": "^5.1.0" @@ -8419,9 +6607,8 @@ }, "node_modules/compare-func/node_modules/dot-prop": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, + "license": "MIT", "dependencies": { "is-obj": "^2.0.0" }, @@ -8431,29 +6618,26 @@ }, "node_modules/compare-func/node_modules/is-obj": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/compute-scroll-into-view": { "version": "1.0.20", - "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz", - "integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "dev": true, + "license": "MIT" }, "node_modules/concordance": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz", - "integrity": "sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==", "dev": true, + "license": "ISC", "dependencies": { "date-time": "^3.1.0", "esutils": "^2.0.3", @@ -8469,51 +6653,35 @@ } }, "node_modules/concurrently": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.6.0.tgz", - "integrity": "sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==", + "version": "8.2.2", "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "date-fns": "^2.29.1", + "chalk": "^4.1.2", + "date-fns": "^2.30.0", "lodash": "^4.17.21", - "rxjs": "^7.0.0", - "shell-quote": "^1.7.3", - "spawn-command": "^0.0.2-1", - "supports-color": "^8.1.0", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "spawn-command": "0.0.2", + "supports-color": "^8.1.1", "tree-kill": "^1.2.2", - "yargs": "^17.3.1" + "yargs": "^17.7.2" }, "bin": { "conc": "dist/bin/concurrently.js", "concurrently": "dist/bin/concurrently.js" }, "engines": { - "node": "^12.20.0 || ^14.13.0 || >=16.0.0" + "node": "^14.13.0 || >=16.0.0" }, "funding": { "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, - "node_modules/concurrently/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/concurrently/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, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -8524,47 +6692,10 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/concurrently/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/concurrently/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/concurrently/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/config-chain": { "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "dev": true, + "license": "MIT", "dependencies": { "ini": "^1.3.4", "proto-list": "~1.2.1" @@ -8572,23 +6703,20 @@ }, "node_modules/console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/convert-to-spaces": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", - "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, "node_modules/core-util-is": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "license": "MIT" }, "node_modules/corser": { "version": "2.0.1", @@ -8600,11 +6728,35 @@ "node": ">= 0.4.0" } }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/cowsay": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cowsay/-/cowsay-1.5.0.tgz", - "integrity": "sha512-8Ipzr54Z8zROr/62C8f0PdhQcDusS05gKTS87xxdji8VbWefWly0k8BwGK7+VqamOrkv3eGsCkPtvlHzrhWsCA==", + "version": "1.6.0", "dev": true, + "license": "MIT", "dependencies": { "get-stdin": "8.0.0", "string-width": "~2.1.1", @@ -8621,18 +6773,16 @@ }, "node_modules/cowsay/node_modules/ansi-regex": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/cowsay/node_modules/find-up": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -8643,18 +6793,16 @@ }, "node_modules/cowsay/node_modules/is-fullwidth-code-point": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/cowsay/node_modules/locate-path": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -8664,9 +6812,8 @@ }, "node_modules/cowsay/node_modules/p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -8679,9 +6826,8 @@ }, "node_modules/cowsay/node_modules/p-locate": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -8691,9 +6837,8 @@ }, "node_modules/cowsay/node_modules/string-width": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, + "license": "MIT", "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" @@ -8704,9 +6849,8 @@ }, "node_modules/cowsay/node_modules/strip-ansi": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^3.0.0" }, @@ -8716,9 +6860,8 @@ }, "node_modules/cowsay/node_modules/yargs": { "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -8738,9 +6881,8 @@ }, "node_modules/cowsay/node_modules/yargs-parser": { "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, + "license": "ISC", "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -8751,27 +6893,24 @@ }, "node_modules/cowsay/node_modules/yargs/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, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/cowsay/node_modules/yargs/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, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/cowsay/node_modules/yargs/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, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -8783,9 +6922,8 @@ }, "node_modules/cowsay/node_modules/yargs/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, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -8795,8 +6933,6 @@ }, "node_modules/cpu-features": { "version": "0.0.9", - "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.9.tgz", - "integrity": "sha512-AKjgn2rP2yJyfbepsmLfiYcmtNn/2eUvocUyM/09yB0YDiz39HteK/5/T4Onf0pmdYDMgkBoGvRLvEguzyL7wQ==", "hasInstallScript": true, "optional": true, "dependencies": { @@ -8809,9 +6945,8 @@ }, "node_modules/create-jest": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", @@ -8828,41 +6963,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/create-jest/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-jest/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/create-jest/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/create-jest/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/create-jest/node_modules/camelcase": { + "version": "6.3.0", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -8872,9 +6976,8 @@ }, "node_modules/create-jest/node_modules/diff": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, + "license": "BSD-3-Clause", "optional": true, "peer": true, "engines": { @@ -8883,9 +6986,8 @@ }, "node_modules/create-jest/node_modules/jest-config": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.7.0", @@ -8926,29 +7028,18 @@ } } }, - "node_modules/create-jest/node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/create-jest/node_modules/jest-regex-util": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/create-jest/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -8963,9 +7054,8 @@ }, "node_modules/create-jest/node_modules/jest-validate": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "camelcase": "^6.2.0", @@ -8978,31 +7068,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/create-jest/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-jest/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/create-jest/node_modules/ts-node": { "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, + "license": "MIT", "optional": true, "peer": true, "dependencies": { @@ -9045,9 +7114,8 @@ }, "node_modules/create-jest/node_modules/yn": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, + "license": "MIT", "optional": true, "peer": true, "engines": { @@ -9056,16 +7124,14 @@ }, "node_modules/create-require": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true, + "license": "MIT", "optional": true, "peer": 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==", + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -9077,15 +7143,13 @@ }, "node_modules/cuint": { "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", - "integrity": "sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/currently-unhandled": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==", "dev": true, + "license": "MIT", "dependencies": { "array-find-index": "^1.0.1" }, @@ -9095,26 +7159,23 @@ }, "node_modules/data-uri-to-buffer": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 12" } }, "node_modules/dataobject-parser": { "version": "1.2.25", - "resolved": "https://registry.npmjs.org/dataobject-parser/-/dataobject-parser-1.2.25.tgz", - "integrity": "sha512-BmHeQBJsyWNKrBtwAzdZYrbnToPJb2zDfB4l/rwXp7bzMY596cGkrZ3qiIhuK+PeWopVKdKMp6nG/CtKKr8wHg==", + "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/date-fns": { "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.21.0" }, @@ -9127,18 +7188,16 @@ } }, "node_modules/date-format": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.9.tgz", - "integrity": "sha512-+8J+BOUpSrlKLQLeF8xJJVTxS8QfRSuJgwxSVvslzgO3E6khbI0F5mMEPf5mTYhCCm4h99knYP6H3W9n3BQFrg==", + "version": "4.0.14", + "license": "MIT", "engines": { "node": ">=4.0" } }, "node_modules/date-time": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/date-time/-/date-time-3.1.0.tgz", - "integrity": "sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==", "dev": true, + "license": "MIT", "dependencies": { "time-zone": "^1.0.0" }, @@ -9148,8 +7207,7 @@ }, "node_modules/debug": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -9164,73 +7222,78 @@ }, "node_modules/debuglog": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", - "integrity": "sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, "node_modules/decamelize": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/dedent": { + "version": "1.5.3", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, "node_modules/deep-diff": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz", - "integrity": "sha512-yVn6RZmHiGnxRKR9sJb3iVV2XTF1Ghh2DiWRZ3dMnGc43yUdWWF/kX6lQyk3+P84iprfWKU/8zFTrlkvtFm1ug==", - "dev": true + "version": "1.0.2", + "dev": true, + "license": "MIT" }, "node_modules/deep-extend": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4.0.0" } }, "node_modules/deep-is": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "version": "4.3.1", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/deepmerge-ts": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-5.1.0.tgz", - "integrity": "sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=16.0.0" } }, "node_modules/defaults": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, + "license": "MIT", "dependencies": { "clone": "^1.0.2" } }, "node_modules/defaults/node_modules/clone": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8" } @@ -9240,6 +7303,7 @@ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -9252,292 +7316,238 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/del": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", - "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", - "dev": true, - "dependencies": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/delegate": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", - "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/depd": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/dependency-tree": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/dependency-tree/-/dependency-tree-8.1.2.tgz", - "integrity": "sha512-c4CL1IKxkKng0oT5xrg4uNiiMVFqTGOXqHSFx7XEFdgSsp6nw3AGGruICppzJUrfad/r7GLqt26rmWU4h4j39A==", + "version": "10.0.9", "dev": true, + "license": "MIT", "dependencies": { - "commander": "^2.20.3", - "debug": "^4.3.1", - "filing-cabinet": "^3.0.1", - "precinct": "^8.0.0", - "typescript": "^3.9.7" + "commander": "^10.0.1", + "filing-cabinet": "^4.1.6", + "precinct": "^11.0.5", + "typescript": "^5.0.4" }, "bin": { "dependency-tree": "bin/cli.js" }, "engines": { - "node": "^10.13 || ^12 || >=14" + "node": ">=14" } }, "node_modules/dependency-tree/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/dependency-tree/node_modules/precinct": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/precinct/-/precinct-8.3.1.tgz", - "integrity": "sha512-pVppfMWLp2wF68rwHqBIpPBYY8Kd12lDhk8LVQzOwqllifVR15qNFyod43YLyFpurKRZQKnE7E4pofAagDOm2Q==", + "version": "10.0.1", "dev": true, - "dependencies": { - "commander": "^2.20.3", - "debug": "^4.3.3", - "detective-amd": "^3.1.0", - "detective-cjs": "^3.1.1", - "detective-es6": "^2.2.1", - "detective-less": "^1.0.2", - "detective-postcss": "^4.0.0", - "detective-sass": "^3.0.1", - "detective-scss": "^2.0.1", - "detective-stylus": "^1.0.0", - "detective-typescript": "^7.0.0", - "module-definition": "^3.3.1", - "node-source-walk": "^4.2.0" - }, - "bin": { - "precinct": "bin/cli.js" - }, + "license": "MIT", "engines": { - "node": "^10.13 || ^12 || >=14" + "node": ">=14" } }, - "node_modules/dependency-tree/node_modules/typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "node_modules/detect-indent": { + "version": "7.0.1", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "license": "MIT", "engines": { - "node": ">=4.2.0" + "node": ">=12.20" } }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true + "node_modules/detect-libc": { + "version": "2.0.3", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } }, "node_modules/detect-newline": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/detective-amd": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detective-amd/-/detective-amd-3.1.0.tgz", - "integrity": "sha512-G7wGWT6f0VErjUkE2utCm7IUshT7nBh7aBBH2VBOiY9Dqy2DMens5iiOvYCuhstoIxRKLrnOvVAz4/EyPIAjnw==", + "version": "5.0.2", "dev": true, + "license": "MIT", "dependencies": { - "ast-module-types": "^2.7.0", + "ast-module-types": "^5.0.0", "escodegen": "^2.0.0", - "get-amd-module-type": "^3.0.0", - "node-source-walk": "^4.0.0" + "get-amd-module-type": "^5.0.1", + "node-source-walk": "^6.0.1" }, "bin": { - "detective-amd": "bin/detective-amd.js" + "detective-amd": "bin/cli.js" }, "engines": { - "node": ">= 6.0" + "node": ">=14" } }, "node_modules/detective-cjs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/detective-cjs/-/detective-cjs-3.1.1.tgz", - "integrity": "sha512-JQtNTBgFY6h8uT6pgph5QpV3IyxDv+z3qPk/FZRDT9TlFfm5dnRtpH39WtQEr1khqsUxVqXzKjZHpdoQvQbllg==", + "version": "5.0.1", "dev": true, + "license": "MIT", "dependencies": { - "ast-module-types": "^2.4.0", - "node-source-walk": "^4.0.0" + "ast-module-types": "^5.0.0", + "node-source-walk": "^6.0.0" }, "engines": { - "node": ">= 6.0" + "node": ">=14" } }, "node_modules/detective-es6": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/detective-es6/-/detective-es6-2.2.1.tgz", - "integrity": "sha512-22z7MblxkhsIQGuALeGwCKEfqNy4WmgDGmfJCwdXbfDkVYIiIDmY513hiIWBvX3kCmzvvWE7RR7kAYxs01wwKQ==", - "dev": true, - "dependencies": { - "node-source-walk": "^4.0.0" - }, - "engines": { - "node": ">= 6.0" - } - }, - "node_modules/detective-less": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/detective-less/-/detective-less-1.0.2.tgz", - "integrity": "sha512-Rps1xDkEEBSq3kLdsdnHZL1x2S4NGDcbrjmd4q+PykK5aJwDdP5MBgrJw1Xo+kyUHuv3JEzPqxr+Dj9ryeDRTA==", + "version": "4.0.1", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.0.0", - "gonzales-pe": "^4.2.3", - "node-source-walk": "^4.0.0" + "node-source-walk": "^6.0.1" }, "engines": { - "node": ">= 6.0" + "node": ">=14" } }, "node_modules/detective-postcss": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detective-postcss/-/detective-postcss-4.0.0.tgz", - "integrity": "sha512-Fwc/g9VcrowODIAeKRWZfVA/EufxYL7XfuqJQFroBKGikKX83d2G7NFw6kDlSYGG3LNQIyVa+eWv1mqre+v4+A==", + "version": "6.1.3", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.1.1", "is-url": "^1.2.4", - "postcss": "^8.1.7", - "postcss-values-parser": "^2.0.1" + "postcss": "^8.4.23", + "postcss-values-parser": "^6.0.2" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/detective-sass": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/detective-sass/-/detective-sass-3.0.1.tgz", - "integrity": "sha512-oSbrBozRjJ+QFF4WJFbjPQKeakoaY1GiR380NPqwdbWYd5wfl5cLWv0l6LsJVqrgWfFN1bjFqSeo32Nxza8Lbw==", + "version": "5.0.3", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.1.1", - "gonzales-pe": "^4.2.3", - "node-source-walk": "^4.0.0" + "gonzales-pe": "^4.3.0", + "node-source-walk": "^6.0.1" }, "engines": { - "node": ">= 6.0" + "node": ">=14" } }, "node_modules/detective-scss": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detective-scss/-/detective-scss-2.0.1.tgz", - "integrity": "sha512-VveyXW4WQE04s05KlJ8K0bG34jtHQVgTc9InspqoQxvnelj/rdgSAy7i2DXAazyQNFKlWSWbS+Ro2DWKFOKTPQ==", + "version": "4.0.3", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.1.1", - "gonzales-pe": "^4.2.3", - "node-source-walk": "^4.0.0" + "gonzales-pe": "^4.3.0", + "node-source-walk": "^6.0.1" }, "engines": { - "node": ">= 6.0" + "node": ">=14" } }, "node_modules/detective-stylus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detective-stylus/-/detective-stylus-1.0.0.tgz", - "integrity": "sha1-UK7n24uruZA4HwEMY/q7pbWOVM0=", - "dev": true + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } }, "node_modules/detective-typescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/detective-typescript/-/detective-typescript-7.0.0.tgz", - "integrity": "sha512-y/Ev98AleGvl43YKTNcA2Q+lyFmsmCfTTNWy4cjEJxoLkbobcXtRS0Kvx06daCgr2GdtlwLfNzL553BkktfJoA==", + "version": "11.2.0", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "^4.8.2", - "ast-module-types": "^2.7.1", - "node-source-walk": "^4.2.0", - "typescript": "^3.9.7" + "@typescript-eslint/typescript-estree": "^5.62.0", + "ast-module-types": "^5.0.0", + "node-source-walk": "^6.0.2", + "typescript": "^5.4.4" }, "engines": { - "node": "^10.13 || >=12.0.0" + "node": "^14.14.0 || >=16.0.0" } }, - "node_modules/detective-typescript/node_modules/typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "node_modules/detective-typescript/node_modules/@typescript-eslint/types": { + "version": "5.62.0", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/detective-typescript/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" }, "engines": { - "node": ">=4.2.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/detective-typescript/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, "node_modules/dezalgo": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", - "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", "dev": true, + "license": "ISC", "dependencies": { "asap": "^2.0.0", "wrappy": "1" @@ -9545,25 +7555,23 @@ }, "node_modules/diff": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/diff-sequences": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.4.0.tgz", - "integrity": "sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww==", + "version": "29.6.3", + "license": "MIT", "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/diff2html": { "version": "3.4.48", - "resolved": "https://registry.npmjs.org/diff2html/-/diff2html-3.4.48.tgz", - "integrity": "sha512-1lzNSg0G0VPKZPTyi4knzV2nAWTXBy/QaWCKzDto6iEIlcuOJEG0li4bElJfpHNz+pBqPu4AcC1i9ZCo9KMUOg==", "dev": true, + "license": "MIT", "dependencies": { "diff": "5.1.0", "hogan.js": "3.0.2" @@ -9577,9 +7585,8 @@ }, "node_modules/dir-glob": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -9589,9 +7596,8 @@ }, "node_modules/doctrine": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -9601,26 +7607,22 @@ }, "node_modules/duplexer": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/eastasianwidth": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + "license": "MIT" }, "node_modules/electron-to-chromium": { "version": "1.4.692", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.692.tgz", - "integrity": "sha512-d5rZRka9n2Y3MkWRN74IoAsxR0HK3yaAt7T50e3iT9VZmCCQDT3geXUO5ZRMhDToa1pkCeQXuNo+0g+NfDOVPA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/emittery": { "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -9630,13 +7632,11 @@ }, "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==" + "license": "MIT" }, "node_modules/encoding": { "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", "optional": true, "dependencies": { "iconv-lite": "^0.6.2" @@ -9644,8 +7644,7 @@ }, "node_modules/encoding/node_modules/iconv-lite": { "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", "optional": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -9655,10 +7654,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz", - "integrity": "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==", + "version": "5.17.0", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -9669,8 +7667,7 @@ }, "node_modules/entities": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, @@ -9680,9 +7677,8 @@ }, "node_modules/env-cmd": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/env-cmd/-/env-cmd-10.1.0.tgz", - "integrity": "sha512-mMdWTT9XKN7yNth/6N6g2GuKuJTsKMDHlQFUDacb/heQRRWOTIZ42t1rMHnQu4jYxU1ajdTeJM+9eEETlqToMA==", "dev": true, + "license": "MIT", "dependencies": { "commander": "^4.0.0", "cross-spawn": "^7.0.0" @@ -9696,31 +7692,27 @@ }, "node_modules/env-cmd/node_modules/commander": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/env-paths": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/err-code": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" + "license": "MIT" }, "node_modules/error-ex": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, + "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } @@ -9730,6 +7722,7 @@ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, + "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -9742,24 +7735,22 @@ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/escalade": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, + "license": "MIT", "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, + "license": "MIT", "engines": { "node": ">=10" }, @@ -9769,9 +7760,8 @@ }, "node_modules/escodegen": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -9790,56 +7780,54 @@ }, "node_modules/escodegen/node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/eslint": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.25.0.tgz", - "integrity": "sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==", + "version": "8.57.0", "dev": true, + "license": "MIT", "dependencies": { - "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.10.5", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", - "ajv": "^6.10.0", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", - "globby": "^11.1.0", - "grapheme-splitter": "^1.0.4", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "js-sdsl": "^4.1.4", + "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "bin": { @@ -9853,67 +7841,91 @@ } }, "node_modules/eslint-plugin-deprecation": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-deprecation/-/eslint-plugin-deprecation-2.0.0.tgz", - "integrity": "sha512-OAm9Ohzbj11/ZFyICyR5N6LbOIvQMp7ZU2zI7Ej0jIc8kiGUERXPNMfw2QqqHD1ZHtjMub3yPZILovYEYucgoQ==", + "version": "3.0.0", "dev": true, + "license": "LGPL-3.0-or-later", "dependencies": { - "@typescript-eslint/utils": "^6.0.0", - "tslib": "^2.3.1", - "tsutils": "^3.21.0" + "@typescript-eslint/utils": "^7.0.0", + "ts-api-utils": "^1.3.0", + "tslib": "^2.3.1" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0", + "eslint": "^8.0.0", "typescript": "^4.2.4 || ^5.0.0" } }, - "node_modules/eslint-plugin-deprecation/node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "node_modules/eslint-plugin-deprecation/node_modules/tslib": { + "version": "2.6.2", + "dev": true, + "license": "0BSD" + }, + "node_modules/eslint-plugin-jest": { + "version": "27.9.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^5.10.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", + "eslint": "^7.0.0 || ^8.0.0", + "jest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/eslint-plugin-deprecation/node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/types": { + "version": "5.62.0", "dev": true, + "license": "MIT", "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/eslint-plugin-deprecation/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "semver": "^7.3.7", + "tsutils": "^3.21.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", @@ -9925,119 +7937,51 @@ } } }, - "node_modules/eslint-plugin-deprecation/node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils": { + "version": "5.62.0", "dev": true, + "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/eslint-plugin-deprecation/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/eslint-plugin-deprecation/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/eslint-plugin-deprecation/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-deprecation/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/eslint-plugin-deprecation/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, - "node_modules/eslint-plugin-jest": { - "version": "26.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.9.0.tgz", - "integrity": "sha512-TWJxWGp1J628gxh2KhaH1H1paEdgE2J61BBF1I59c6xWeL5+D1BzMxGDN/nXAfX+aSkR5u80K+XhskK6Gwq9ng==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "^5.10.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "jest": { - "optional": true - } - } - }, "node_modules/eslint-plugin-unused-imports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz", - "integrity": "sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==", + "version": "3.2.0", "dev": true, + "license": "MIT", "dependencies": { "eslint-rule-composer": "^0.3.0" }, @@ -10045,8 +7989,8 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0", - "eslint": "^8.0.0" + "@typescript-eslint/eslint-plugin": "6 - 7", + "eslint": "8" }, "peerDependenciesMeta": { "@typescript-eslint/eslint-plugin": { @@ -10056,18 +8000,16 @@ }, "node_modules/eslint-rule-composer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", - "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", "dev": true, + "license": "MIT", "engines": { "node": ">=4.0.0" } }, "node_modules/eslint-scope": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -10076,69 +8018,44 @@ "node": ">=8.0.0" } }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, + "license": "Apache-2.0", "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "7.2.2", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -10147,14 +8064,13 @@ } }, "node_modules/espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", + "version": "9.6.1", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -10163,19 +8079,9 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/esprima": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -10185,10 +8091,9 @@ } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.5.0", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -10198,18 +8103,16 @@ }, "node_modules/esquery/node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/esrecurse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -10219,70 +8122,42 @@ }, "node_modules/esrecurse/node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/estraverse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, "node_modules/esutils": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", - "dev": true, - "dependencies": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, - "node_modules/event-stream/node_modules/split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", - "dev": true, - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "version": "5.0.1", "dev": true, "license": "MIT" }, "node_modules/execa": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -10303,8 +8178,6 @@ }, "node_modules/exit": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", "dev": true, "engines": { "node": ">= 0.8.0" @@ -10312,9 +8185,8 @@ }, "node_modules/expect": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/expect-utils": "^29.7.0", "jest-get-type": "^29.6.3", @@ -10326,20 +8198,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/expect/node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/expect/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -10354,14 +8216,12 @@ }, "node_modules/exponential-backoff": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", - "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==" + "license": "Apache-2.0" }, "node_modules/external-editor": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, + "license": "MIT", "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", @@ -10372,36 +8232,29 @@ } }, "node_modules/fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "version": "2.0.0", "dev": true, + "license": "MIT", "dependencies": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" + "color-support": "^1.1.3" }, "engines": { - "node": ">= 0.10" + "node": ">=10.13.0" } }, "node_modules/fast-deep-equal": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-diff": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "version": "3.3.2", + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -10410,47 +8263,43 @@ "micromatch": "^4.0.4" }, "engines": { - "node": ">=8" + "node": ">=8.6.0" } }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==" + "version": "1.0.16", + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } }, "node_modules/fastq": { "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, "node_modules/fb-watchman": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "bser": "2.1.1" } }, "node_modules/fetch-blob": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", "dev": true, "funding": [ { @@ -10462,6 +8311,7 @@ "url": "https://paypal.me/jimmywarting" } ], + "license": "MIT", "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" @@ -10470,35 +8320,10 @@ "node": "^12.20 || >= 14.13" } }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/file-entry-cache": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" }, @@ -10506,55 +8331,47 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, "node_modules/filing-cabinet": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/filing-cabinet/-/filing-cabinet-3.1.0.tgz", - "integrity": "sha512-ZFutWTo14Z1xmog76UoQzDKEza1fSpqc+HvUN6K6GILrfhIn6NbR8fHQktltygF+wbt7PZ/EvfLK6yJnebd40A==", + "version": "4.2.0", "dev": true, + "license": "MIT", "dependencies": { "app-module-path": "^2.2.0", - "commander": "^2.20.3", - "debug": "^4.3.3", - "enhanced-resolve": "^5.8.3", + "commander": "^10.0.1", + "enhanced-resolve": "^5.14.1", "is-relative-path": "^1.0.2", - "module-definition": "^3.3.1", - "module-lookup-amd": "^7.0.1", - "resolve": "^1.21.0", - "resolve-dependency-path": "^2.0.0", - "sass-lookup": "^3.0.0", - "stylus-lookup": "^3.0.1", - "typescript": "^3.9.7" + "module-definition": "^5.0.1", + "module-lookup-amd": "^8.0.5", + "resolve": "^1.22.3", + "resolve-dependency-path": "^3.0.2", + "sass-lookup": "^5.0.1", + "stylus-lookup": "^5.0.1", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.0.4" }, "bin": { "filing-cabinet": "bin/cli.js" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" } }, "node_modules/filing-cabinet/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/filing-cabinet/node_modules/typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "version": "10.0.1", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "license": "MIT", "engines": { - "node": ">=4.2.0" + "node": ">=14" } }, "node_modules/fill-range": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -10564,14 +8381,12 @@ }, "node_modules/find-package-json": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/find-package-json/-/find-package-json-1.2.0.tgz", - "integrity": "sha512-+SOGcLGYDJHtyqHd87ysBhmaeQ95oWspDKnMXBrnQ9Eq4OkLNqejgoaD8xVWu6GPa0B6roa6KinCMEMcVeqONw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/find-process": { "version": "1.4.7", - "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.7.tgz", - "integrity": "sha512-/U4CYp1214Xrp3u3Fqr9yNynUrr5Le4y0SsJh2lMDDSbpwYSz3M2SMWQC+wqcx79cN8PQtHQIL8KnuY9M66fdg==", + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "commander": "^5.1.0", @@ -10583,8 +8398,7 @@ }, "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==", + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -10596,11 +8410,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-up-simple": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/flat-cache": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.1.0", "rimraf": "^3.0.2" @@ -10611,9 +8435,8 @@ }, "node_modules/flat-cache/node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -10625,16 +8448,8 @@ } }, "node_modules/flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" - }, - "node_modules/flatten": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", - "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", - "deprecated": "flatten is deprecated in favor of utility frameworks such as lodash.", - "dev": true + "version": "3.3.1", + "license": "ISC" }, "node_modules/follow-redirects": { "version": "1.15.9", @@ -10659,8 +8474,7 @@ }, "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==", + "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -10674,8 +8488,7 @@ }, "node_modules/foreground-child/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==", + "license": "ISC", "engines": { "node": ">=14" }, @@ -10685,9 +8498,8 @@ }, "node_modules/form-data": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -10699,9 +8511,8 @@ }, "node_modules/formdata-polyfill": { "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", "dev": true, + "license": "MIT", "dependencies": { "fetch-blob": "^3.1.2" }, @@ -10709,43 +8520,21 @@ "node": ">=12.20.0" } }, - "node_modules/from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", - "dev": true - }, "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "version": "11.2.0", "license": "MIT", "dependencies": { - "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" }, "engines": { - "node": ">=10" - } - }, - "node_modules/fs-extra/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "node": ">=14.14" } }, "node_modules/fs-minipass": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -10755,13 +8544,13 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "dev": true, + "license": "ISC" }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -10774,87 +8563,62 @@ }, "node_modules/function-arguments": { "version": "1.0.9", - "resolved": "https://registry.npmjs.org/function-arguments/-/function-arguments-1.0.9.tgz", - "integrity": "sha512-1Q6pDUjG3uve/ecbHEFpKUUOiPJzg6MZQV51f8c5pqlw1V6KCePQiztzOpQpdR/jnVJPXL2Q02xX1vNV22xx2Q==", "dev": true, + "license": "MIT", "funding": { "url": "https://ko-fi.com/tunnckoCore/commissions" } }, "node_modules/function-bind": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gauge": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-5.0.1.tgz", - "integrity": "sha512-CmykPMJGuNan/3S4kZOpvvPYSNqSHANiWnh9XcMU2pSjtBfF0XzZ2p1bFAxTbnFxyBuPxQYHhzwaoOmUdqzvxQ==", - "dev": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^4.0.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/gauge/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" - }, + "license": "MIT", "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/get-amd-module-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-amd-module-type/-/get-amd-module-type-3.0.0.tgz", - "integrity": "sha512-99Q7COuACPfVt18zH9N4VAMyb81S6TUgJm2NgV6ERtkh9VIkAaByZkW530wl3lLN5KTtSrK9jVLxYsoP5hQKsw==", + "version": "5.0.1", "dev": true, + "license": "MIT", "dependencies": { - "ast-module-types": "^2.3.2", - "node-source-walk": "^4.0.0" + "ast-module-types": "^5.0.0", + "node-source-walk": "^6.0.1" }, "engines": { - "node": ">=6.0" + "node": ">=14" } }, "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==", + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-function-arguments": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-function-arguments/-/get-function-arguments-1.0.0.tgz", - "integrity": "sha512-YQjTJR9BBAmY3lZAy9C0MU1Bm2gE1CLu0KtiU1VpFC9rFNtxTDUnqz+Ut18H87TGiZxhdKzFr+xIadTlhoAjXA==", "dev": true, + "license": "MIT", "dependencies": { "function-arguments": "^1.0.0" } @@ -10864,6 +8628,7 @@ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -10880,24 +8645,21 @@ }, "node_modules/get-own-enumerable-property-symbols": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/get-package-type": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.0.0" } }, "node_modules/get-stdin": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -10907,8 +8669,8 @@ }, "node_modules/get-stream": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -10918,9 +8680,8 @@ }, "node_modules/git-up": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz", - "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==", "dev": true, + "license": "MIT", "dependencies": { "is-ssh": "^1.4.0", "parse-url": "^8.1.0" @@ -10931,6 +8692,7 @@ "resolved": "https://registry.npmjs.org/github-markdown-css/-/github-markdown-css-5.6.1.tgz", "integrity": "sha512-DItLFgHd+s7HQmk63YN4/TdvLeRqk1QP7pPKTTPrDTYoI5x7f/luJWSOZxesmuxBI2srHp8RDyoZd+9WF+WK8Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -10940,8 +8702,8 @@ }, "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, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -10959,8 +8721,7 @@ }, "node_modules/glob-parent": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -10969,10 +8730,9 @@ } }, "node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "version": "13.24.0", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -10985,9 +8745,8 @@ }, "node_modules/globby": { "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, + "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -11003,27 +8762,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby/node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, "node_modules/gonzales-pe": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz", - "integrity": "sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.5" }, @@ -11036,9 +8778,8 @@ }, "node_modules/good-listener": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", - "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", "dev": true, + "license": "MIT", "dependencies": { "delegate": "^3.1.2" } @@ -11048,6 +8789,7 @@ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, + "license": "MIT", "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -11057,32 +8799,17 @@ }, "node_modules/graceful-fs": { "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true + "license": "ISC" }, - "node_modules/graphviz": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/graphviz/-/graphviz-0.0.9.tgz", - "integrity": "sha512-SmoY2pOtcikmMCqCSy2NO1YsRfu9OO0wpTlOYW++giGjfX1a6gax/m1Fo8IdUd0/3H15cTOfR1SMKwohj4LKsg==", + "node_modules/graphemer": { + "version": "1.4.0", "dev": true, - "dependencies": { - "temp": "~0.4.0" - }, - "engines": { - "node": ">=0.6.8" - } + "license": "MIT" }, "node_modules/handlebars": { "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.0", @@ -11099,29 +8826,16 @@ "uglify-js": "^3.1.4" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "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==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/has-own-prop": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", - "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", + "license": "MIT", "engines": { "node": ">=8" } @@ -11131,6 +8845,7 @@ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" }, @@ -11143,6 +8858,7 @@ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -11155,6 +8871,7 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -11164,15 +8881,13 @@ }, "node_modules/has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -11192,9 +8907,8 @@ }, "node_modules/highlight.js": { "version": "11.9.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", - "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==", "dev": true, + "license": "BSD-3-Clause", "optional": true, "engines": { "node": ">=12.0.0" @@ -11202,8 +8916,6 @@ }, "node_modules/hogan.js": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz", - "integrity": "sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==", "dev": true, "dependencies": { "mkdirp": "0.3.0", @@ -11215,19 +8927,26 @@ }, "node_modules/hogan.js/node_modules/mkdirp": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", - "integrity": "sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", "dev": true, + "license": "MIT/X11", "engines": { "node": "*" } }, "node_modules/holderjs": { "version": "2.9.9", - "resolved": "https://registry.npmjs.org/holderjs/-/holderjs-2.9.9.tgz", - "integrity": "sha512-ceWPz1MrR3dxOoZXiom+G48+l1VPG3TcjBw9fq5iwCiZAMvYX8Aia13GOxT7DoV/AcSyTH7Vvr11ygjZP9qn4w==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/hosted-git-info": { + "version": "7.0.2", + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } }, "node_modules/html-encoding-sniffer": { "version": "3.0.0", @@ -11244,14 +8963,12 @@ }, "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 + "dev": true, + "license": "MIT" }, "node_modules/http-cache-semantics": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + "license": "BSD-2-Clause" }, "node_modules/http-proxy": { "version": "1.18.1", @@ -11270,9 +8987,8 @@ }, "node_modules/http-proxy-agent": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, + "license": "MIT", "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -11284,13 +9000,19 @@ }, "node_modules/http-proxy-agent/node_modules/@tootallnate/once": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10" } }, + "node_modules/http-proxy/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true, + "license": "MIT" + }, "node_modules/http-server": { "version": "14.1.1", "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", @@ -11334,9 +9056,8 @@ }, "node_modules/https-proxy-agent": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "6", "debug": "4" @@ -11347,29 +9068,29 @@ }, "node_modules/human-signals": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10.17.0" } }, "node_modules/humanize-ms": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.0.0" } }, "node_modules/husky": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/husky/-/husky-6.0.0.tgz", - "integrity": "sha512-SQS2gDTB7tBN486QSoKPKQItZw97BMOd+Kdb6ghfpBc0yXyzrddI0oDV5MkDAbuB4X2mO3/nj60TRMcYxwzZeQ==", + "version": "9.0.11", "dev": true, + "license": "MIT", "bin": { - "husky": "lib/bin.js" + "husky": "bin.mjs" + }, + "engines": { + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/typicode" @@ -11377,9 +9098,8 @@ }, "node_modules/iconv-lite": { "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -11389,8 +9109,6 @@ }, "node_modules/ieee754": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true, "funding": [ { @@ -11405,30 +9123,28 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/ignore-by-default": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-2.1.0.tgz", - "integrity": "sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw==", "dev": true, + "license": "ISC", "engines": { "node": ">=10 <11 || >=12 <13 || >=14" } }, "node_modules/ignore-walk": { "version": "6.0.4", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.4.tgz", - "integrity": "sha512-t7sv42WkwFkyKbivUCglsQW5YWMskWtbEf4MNKX5u/CCWHKSPzN4FtBQGsQZgCLbxOzpVlcbWVK5KB3auIOjSw==", + "license": "ISC", "dependencies": { "minimatch": "^9.0.0" }, @@ -11438,16 +9154,14 @@ }, "node_modules/ignore-walk/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==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/ignore-walk/node_modules/minimatch": { "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -11460,9 +9174,8 @@ }, "node_modules/import-fresh": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -11476,18 +9189,16 @@ }, "node_modules/import-fresh/node_modules/resolve-from": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/import-local": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, + "license": "MIT", "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -11504,36 +9215,38 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "license": "MIT", "engines": { "node": ">=0.8.19" } }, "node_modules/indent-string": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true + "node_modules/index-to-position": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/infer-owner": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -11541,19 +9254,52 @@ }, "node_modules/inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "dev": true, + "license": "ISC" }, "node_modules/ini": { "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "dev": true, + "license": "ISC" + }, + "node_modules/inquirer": { + "version": "9.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/figures": "^1.0.3", + "ansi-escapes": "^4.3.2", + "cli-width": "^4.1.0", + "external-editor": "^3.1.0", + "mute-stream": "1.0.0", + "ora": "^5.4.1", + "run-async": "^3.0.0", + "rxjs": "^7.8.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/inquirer/node_modules/wrap-ansi": { + "version": "6.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } }, "node_modules/ip-address": { "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "license": "MIT", "dependencies": { "jsbn": "1.1.0", "sprintf-js": "^1.1.3" @@ -11564,82 +9310,71 @@ }, "node_modules/ip-address/node_modules/sprintf-js": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + "license": "BSD-3-Clause" }, "node_modules/irregular-plurals": { "version": "3.5.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.5.0.tgz", - "integrity": "sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-arrayish": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "dev": true, + "license": "MIT" }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/is-ci": { + "version": "3.0.1", "dev": true, + "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "ci-info": "^3.2.0" }, - "engines": { - "node": ">=8" + "bin": { + "is-ci": "bin.js" } }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.14.0", + "dev": true, + "license": "MIT", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-error": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-error/-/is-error-2.2.2.tgz", - "integrity": "sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==", - "dev": true - }, "node_modules/is-extglob": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "license": "MIT", "engines": { "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==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-generator-fn": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/is-glob": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -11649,97 +9384,88 @@ }, "node_modules/is-interactive": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-lambda": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=" + "license": "MIT" }, "node_modules/is-number": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/is-obj": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "node_modules/is-path-inside": { + "version": "3.0.3", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/is-plain-obj": { + "version": "4.1.0", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-plain-object": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-promise": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-regexp": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-relative-path": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-relative-path/-/is-relative-path-1.0.2.tgz", - "integrity": "sha1-CRtGoNZ8HtD+hfH4z93gBrslHUY=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-ssh": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz", - "integrity": "sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==", "dev": true, + "license": "MIT", "dependencies": { "protocols": "^2.0.1" } }, "node_modules/is-stream": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -11749,15 +9475,13 @@ }, "node_modules/is-typedarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "dev": true, + "license": "MIT" }, "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, + "license": "MIT", "engines": { "node": ">=10" }, @@ -11767,47 +9491,52 @@ }, "node_modules/is-url": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/is-url-superb": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/is-windows": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/isexe": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "license": "ISC" }, "node_modules/isobject": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-instrument": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", @@ -11821,18 +9550,16 @@ }, "node_modules/istanbul-lib-instrument/node_modules/semver": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/istanbul-lib-report": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", @@ -11844,9 +9571,8 @@ }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -11858,9 +9584,8 @@ }, "node_modules/istanbul-reports": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -11871,8 +9596,7 @@ }, "node_modules/jackspeak": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -11888,9 +9612,8 @@ }, "node_modules/jest": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -11914,9 +9637,8 @@ }, "node_modules/jest-changed-files": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, + "license": "MIT", "dependencies": { "execa": "^5.0.0", "jest-util": "^29.7.0", @@ -11928,9 +9650,8 @@ }, "node_modules/jest-changed-files/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -11945,9 +9666,8 @@ }, "node_modules/jest-circus": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/expect": "^29.7.0", @@ -11974,55 +9694,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-circus/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-circus/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/jest-circus/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-circus/node_modules/dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", - "dev": true, - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, "node_modules/jest-circus/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -12035,31 +9710,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-circus/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-circus/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/jest-cli": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/core": "^29.7.0", "@jest/test-result": "^29.7.0", @@ -12088,41 +9742,10 @@ } } }, - "node_modules/jest-cli/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-cli/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/jest-cli/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-cli/node_modules/camelcase": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -12130,25 +9753,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-cli/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/jest-cli/node_modules/diff": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, + "license": "BSD-3-Clause", "optional": true, "peer": true, "engines": { @@ -12157,9 +9765,8 @@ }, "node_modules/jest-cli/node_modules/jest-config": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.7.0", @@ -12200,29 +9807,18 @@ } } }, - "node_modules/jest-cli/node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/jest-cli/node_modules/jest-regex-util": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-cli/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -12237,9 +9833,8 @@ }, "node_modules/jest-cli/node_modules/jest-validate": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "camelcase": "^6.2.0", @@ -12252,31 +9847,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-cli/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-cli/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/jest-cli/node_modules/ts-node": { "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, + "license": "MIT", "optional": true, "peer": true, "dependencies": { @@ -12317,47 +9891,10 @@ } } }, - "node_modules/jest-cli/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/jest-cli/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/jest-cli/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/jest-cli/node_modules/yn": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, + "license": "MIT", "optional": true, "peer": true, "engines": { @@ -12365,69 +9902,22 @@ } }, "node_modules/jest-diff": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.6.tgz", - "integrity": "sha512-Z1mqgkTCSYaFgwTlP/NUiRzdqgxmmhzHY1Tq17zL94morOHfHu3K4bgSgl+CR4GLhpV8VxkuOYuIWnQ9LnFqmg==", + "version": "29.7.0", + "license": "MIT", "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^27.0.6", - "jest-get-type": "^27.0.6", - "pretty-format": "^27.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-diff/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-diff/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-diff/node_modules/jest-get-type": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.4.0.tgz", - "integrity": "sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ==", - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-diff/node_modules/pretty-format": { - "version": "27.4.6", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.4.6.tgz", - "integrity": "sha512-NblstegA1y/RJW2VyML+3LlpFjzx62cUrtBIKIWDXEDkjNeleA7Od7nrzcs/VLQvAeV4CgSYhrN39DRN88Qi/g==", - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-diff/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, "node_modules/jest-docblock": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, + "license": "MIT", "dependencies": { "detect-newline": "^3.0.0" }, @@ -12437,9 +9927,8 @@ }, "node_modules/jest-each": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", @@ -12451,50 +9940,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-each/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/jest-each/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-each/node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/jest-each/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -12507,31 +9956,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-each/node_modules/pretty-format": { + "node_modules/jest-environment-node": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", @@ -12546,15 +9974,12 @@ }, "node_modules/jest-environment-node-debug": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jest-environment-node-debug/-/jest-environment-node-debug-2.0.0.tgz", - "integrity": "sha1-XvCYlC/sG2r17khB9Pii/0GVYvk=", "dev": true }, "node_modules/jest-environment-node/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -12567,11 +9992,17 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-html-reporter": { "version": "3.10.2", - "resolved": "https://registry.npmjs.org/jest-html-reporter/-/jest-html-reporter-3.10.2.tgz", - "integrity": "sha512-XRBa5ylHPUQoo8aJXEEdKsTruieTdlPbRktMx9WG9evMTxzJEKGFMaw5x+sQxJuClWdNR72GGwbOaz+6HIlksA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/test-result": "^29.0.2", "@jest/types": "^29.0.2", @@ -12590,21 +10021,19 @@ }, "node_modules/jest-html-reporter/node_modules/dateformat": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.2.tgz", - "integrity": "sha512-EelsCzH0gMC2YmXuMeaZ3c6md1sUJQxyb1XXc4xaisi/K6qKukqZhKPrEQyRkdNIncgYyLoDTReq0nNyuKerTg==", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, "node_modules/jest-junit": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-12.3.0.tgz", - "integrity": "sha512-+NmE5ogsEjFppEl90GChrk7xgz8xzvF0f+ZT5AnhW6suJC93gvQtmQjfyjDnE0Z2nXJqEkxF0WXlvjG/J+wn/g==", + "version": "16.0.0", "dev": true, + "license": "Apache-2.0", "dependencies": { "mkdirp": "^1.0.4", - "strip-ansi": "^5.2.0", + "strip-ansi": "^6.0.1", "uuid": "^8.3.2", "xml": "^1.0.1" }, @@ -12612,23 +10041,10 @@ "node": ">=10.12.0" } }, - "node_modules/jest-junit/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/jest-leak-detector": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, + "license": "MIT", "dependencies": { "jest-get-type": "^29.6.3", "pretty-format": "^29.7.0" @@ -12637,70 +10053,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-leak-detector/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-leak-detector/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/jest-leak-detector/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-leak-detector/node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-leak-detector/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-leak-detector/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/jest-matcher-utils": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "jest-diff": "^29.7.0", @@ -12711,94 +10067,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-matcher-utils/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/jest-matcher-utils/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-matcher-utils/node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/jest-message-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.6.3", @@ -12814,61 +10086,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-message-util/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/jest-message-util/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-message-util/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/jest-mock": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -12880,9 +10101,8 @@ }, "node_modules/jest-mock/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -12897,9 +10117,8 @@ }, "node_modules/jest-pnp-resolver": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -12914,9 +10133,8 @@ }, "node_modules/jest-resolve": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", @@ -12934,9 +10152,8 @@ }, "node_modules/jest-resolve-dependencies": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, + "license": "MIT", "dependencies": { "jest-regex-util": "^29.6.3", "jest-snapshot": "^29.7.0" @@ -12947,48 +10164,16 @@ }, "node_modules/jest-resolve-dependencies/node_modules/jest-regex-util": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-resolve/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/jest-resolve/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-resolve/node_modules/camelcase": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -12996,20 +10181,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-resolve/node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/jest-resolve/node_modules/jest-haste-map": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", @@ -13032,18 +10207,16 @@ }, "node_modules/jest-resolve/node_modules/jest-regex-util": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -13058,9 +10231,8 @@ }, "node_modules/jest-resolve/node_modules/jest-validate": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "camelcase": "^6.2.0", @@ -13075,9 +10247,8 @@ }, "node_modules/jest-resolve/node_modules/jest-worker": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", @@ -13088,40 +10259,18 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-resolve/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/jest-resolve/node_modules/resolve.exports": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/jest-resolve/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, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -13134,9 +10283,8 @@ }, "node_modules/jest-runner": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^29.7.0", "@jest/environment": "^29.7.0", @@ -13166,9 +10314,8 @@ }, "node_modules/jest-runner/node_modules/@jest/transform": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", @@ -13192,15 +10339,13 @@ }, "node_modules/jest-runner/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 + "dev": true, + "license": "MIT" }, "node_modules/jest-runner/node_modules/jest-haste-map": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", @@ -13223,18 +10368,16 @@ }, "node_modules/jest-runner/node_modules/jest-regex-util": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -13249,9 +10392,8 @@ }, "node_modules/jest-runner/node_modules/jest-worker": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", @@ -13264,9 +10406,8 @@ }, "node_modules/jest-runner/node_modules/source-map-support": { "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -13274,9 +10415,8 @@ }, "node_modules/jest-runner/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, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -13289,9 +10429,8 @@ }, "node_modules/jest-runtime": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", @@ -13322,9 +10461,8 @@ }, "node_modules/jest-runtime/node_modules/@jest/transform": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", @@ -13348,15 +10486,13 @@ }, "node_modules/jest-runtime/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 + "dev": true, + "license": "MIT" }, "node_modules/jest-runtime/node_modules/jest-haste-map": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", @@ -13379,18 +10515,16 @@ }, "node_modules/jest-runtime/node_modules/jest-regex-util": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runtime/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -13405,9 +10539,8 @@ }, "node_modules/jest-runtime/node_modules/jest-worker": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", @@ -13420,9 +10553,8 @@ }, "node_modules/jest-runtime/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, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -13435,9 +10567,8 @@ }, "node_modules/jest-snapshot": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", @@ -13464,23 +10595,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-snapshot/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/jest-snapshot/node_modules/@jest/transform": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", @@ -13502,68 +10620,15 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-snapshot/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/jest-snapshot/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/jest-snapshot/node_modules/convert-source-map": { + "version": "2.0.0", "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-snapshot/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/jest-snapshot/node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "license": "MIT" }, "node_modules/jest-snapshot/node_modules/jest-haste-map": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", @@ -13586,18 +10651,16 @@ }, "node_modules/jest-snapshot/node_modules/jest-regex-util": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -13612,9 +10675,8 @@ }, "node_modules/jest-snapshot/node_modules/jest-worker": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", @@ -13625,31 +10687,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-snapshot/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/jest-snapshot/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, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -13662,9 +10703,8 @@ }, "node_modules/jest-sonar-reporter": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jest-sonar-reporter/-/jest-sonar-reporter-2.0.0.tgz", - "integrity": "sha512-ZervDCgEX5gdUbdtWsjdipLN3bKJwpxbvhkYNXTAYvAckCihobSLr9OT/IuyNIRT1EZMDDwR6DroWtrq+IL64w==", "dev": true, + "license": "MIT", "dependencies": { "xml": "^1.0.1" }, @@ -13673,10 +10713,9 @@ } }, "node_modules/jest-stare": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jest-stare/-/jest-stare-2.5.2.tgz", - "integrity": "sha512-dvxHXOsiJlvBi0n2dK9pz6RWFTdPB6njc2ZoMpyjmWI+aIL+X1W8OW5mTm1pkv/quy2ocKO/G+GsTe7Bv07xkQ==", + "version": "2.5.1", "dev": true, + "license": "MIT", "dependencies": { "@jest/reporters": "^29.0.0", "@jest/test-result": "^29.0.0", @@ -13702,22 +10741,10 @@ "node": ">=6.0.0" } }, - "node_modules/jest-stare/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/jest-stare/node_modules/find-up": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^3.0.0" }, @@ -13727,9 +10754,8 @@ }, "node_modules/jest-stare/node_modules/locate-path": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -13740,9 +10766,8 @@ }, "node_modules/jest-stare/node_modules/p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -13755,9 +10780,8 @@ }, "node_modules/jest-stare/node_modules/p-locate": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.0.0" }, @@ -13767,18 +10791,16 @@ }, "node_modules/jest-stare/node_modules/path-exists": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/jest-stare/node_modules/pkg-up": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^3.0.0" }, @@ -13786,47 +10808,10 @@ "node": ">=8" } }, - "node_modules/jest-stare/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/jest-stare/node_modules/yargs": { - "version": "17.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", - "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", - "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.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/jest-stare/node_modules/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/jest-watcher": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, + "license": "MIT", "dependencies": { "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", @@ -13843,9 +10828,8 @@ }, "node_modules/jest-watcher/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -13862,33 +10846,25 @@ "version": "3.7.1", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", - "dev": true - }, - "node_modules/js-sdsl": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", - "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-string-escape": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", - "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "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==", + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -13898,14 +10874,12 @@ }, "node_modules/jsbn": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + "license": "MIT" }, "node_modules/jsesc": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -13915,42 +10889,36 @@ }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stringify-nice": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz", - "integrity": "sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==", "dev": true, + "license": "ISC", "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/json-stringify-safe": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/json5": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -13958,43 +10926,34 @@ "node": ">=6" } }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, + "version": "6.1.0", "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "node_modules/jsonparse": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "engines": [ "node >= 0.2.0" - ] + ], + "license": "MIT" }, "node_modules/jsonschema": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", - "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", + "license": "MIT", "engines": { "node": "*" } }, "node_modules/JSONStream": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", "dev": true, + "license": "(MIT OR Apache-2.0)", "dependencies": { "jsonparse": "^1.2.0", "through": ">=2.2.7 <3" @@ -14008,48 +10967,50 @@ }, "node_modules/jstree": { "version": "3.3.16", - "resolved": "https://registry.npmjs.org/jstree/-/jstree-3.3.16.tgz", - "integrity": "sha512-yeeIJffi2WAqyMeHufXj/Ozy7GqgKdDkxfN8L8lwbG0h1cw/TgDafWmyhroH4AKgDSk9yW1W6jiJZu4zXAqzXw==", "dev": true, + "license": "MIT", "dependencies": { "jquery": "^3.5.0" } }, "node_modules/just-diff": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-5.1.1.tgz", - "integrity": "sha512-u8HXJ3HlNrTzY7zrYYKjNEfBlyjqhdBkoyTVdjtn7p02RJD5NvR8rIClzeGA7t+UYP1/7eAkWNLU0+P3QrEqKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/just-diff-apply": { "version": "5.4.1", - "resolved": "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-5.4.1.tgz", - "integrity": "sha512-AAV5Jw7tsniWwih8Ly3fXxEZ06y+6p5TwQMsw0dzZ/wPKilzyDgdAnL0Ug4NNIquPUOh1vfFWEHbmXUqM5+o8g==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/kind-of": { + "version": "6.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, "node_modules/kleur": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/leven": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/levn": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -14060,22 +11021,30 @@ }, "node_modules/lines-and-columns": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/linkify-it": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "license": "MIT", "dependencies": { "uc.micro": "^2.0.0" } }, + "node_modules/load-json-file": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "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==", + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -14088,13 +11057,11 @@ }, "node_modules/lodash": { "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "license": "MIT" }, "node_modules/lodash-deep": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lodash-deep/-/lodash-deep-2.0.0.tgz", - "integrity": "sha1-ypWPW82z1o0+w3rN8cWMHMvYhlw=", + "license": "MIT", "dependencies": { "lodash": ">=3.7.0" }, @@ -14105,21 +11072,18 @@ }, "node_modules/lodash.memoize": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "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, + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -14132,15 +11096,14 @@ } }, "node_modules/log4js": { - "version": "6.4.6", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.6.tgz", - "integrity": "sha512-1XMtRBZszmVZqPAOOWczH+Q94AI42mtNWjvjA5RduKTSWjEc56uOBbyM1CJnfN4Ym0wSd8cQ43zOojlSHgRDAw==", + "version": "6.9.1", + "license": "Apache-2.0", "dependencies": { - "date-format": "^4.0.9", + "date-format": "^4.0.14", "debug": "^4.3.4", - "flatted": "^3.2.5", + "flatted": "^3.2.7", "rfdc": "^1.3.0", - "streamroller": "^3.0.8" + "streamroller": "^3.1.5" }, "engines": { "node": ">=8.0" @@ -14148,85 +11111,66 @@ }, "node_modules/lru-cache": { "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "license": "ISC", "engines": { "node": "14 || >=16.14" } }, "node_modules/lunr": { "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/madge": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/madge/-/madge-4.0.2.tgz", - "integrity": "sha512-l5bnA2dvyk0azLKDbOTCI+wDZ6nB007PhvPdmiYlPmqwVi49JPbhQrH/t4u8E6Akp3gwji1GZuA+v/F5q6yoWQ==", + "version": "7.0.0", "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "commander": "^6.2.1", + "chalk": "^4.1.2", + "commander": "^7.2.0", "commondir": "^1.0.1", - "debug": "^4.0.1", - "dependency-tree": "^8.0.0", - "detective-amd": "^3.0.1", - "detective-cjs": "^3.1.1", - "detective-es6": "^2.1.0", - "detective-less": "^1.0.2", - "detective-postcss": "^4.0.0", - "detective-sass": "^3.0.1", - "detective-scss": "^2.0.1", - "detective-stylus": "^1.0.0", - "detective-typescript": "^7.0.0", - "graphviz": "0.0.9", - "ora": "^5.1.0", + "debug": "^4.3.4", + "dependency-tree": "^10.0.9", + "ora": "^5.4.1", "pluralize": "^8.0.0", - "precinct": "^7.0.0", - "pretty-ms": "^7.0.0", - "rc": "^1.2.7", - "typescript": "^3.9.5", + "precinct": "^11.0.5", + "pretty-ms": "^7.0.1", + "rc": "^1.2.8", + "stream-to-array": "^2.3.0", + "ts-graphviz": "^1.8.1", "walkdir": "^0.4.1" }, "bin": { "madge": "bin/cli.js" }, "engines": { - "node": "^10.13 || ^12 || >=14" + "node": ">=14" }, "funding": { "type": "individual", "url": "https://www.paypal.me/pahen" + }, + "peerDependencies": { + "typescript": "^3.9.5 || ^4.9.5 || ^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/madge/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/madge/node_modules/typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "version": "7.2.0", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "license": "MIT", "engines": { - "node": ">=4.2.0" + "node": ">= 10" } }, "node_modules/make-dir": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^6.0.0" }, @@ -14239,24 +11183,21 @@ }, "node_modules/make-dir/node_modules/semver": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/make-error": { "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/make-fetch-happen": { "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", "dev": true, + "license": "ISC", "dependencies": { "agentkeepalive": "^4.2.1", "cacache": "^16.1.0", @@ -14281,18 +11222,16 @@ }, "node_modules/make-fetch-happen/node_modules/lru-cache": { "version": "7.14.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz", - "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } }, "node_modules/make-fetch-happen/node_modules/minipass-fetch": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", "dev": true, + "license": "MIT", "dependencies": { "minipass": "^3.1.6", "minipass-sized": "^1.0.3", @@ -14307,35 +11246,15 @@ }, "node_modules/makeerror": { "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "tmpl": "1.0.5" } }, - "node_modules/map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "dependencies": { - "p-defer": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==", - "dev": true - }, "node_modules/markdown-it": { "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "license": "MIT", "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", @@ -14348,23 +11267,10 @@ "markdown-it": "bin/markdown-it.mjs" } }, - "node_modules/marked": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.1.tgz", - "integrity": "sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw==", - "dev": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, "node_modules/matcher": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-5.0.0.tgz", - "integrity": "sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^5.0.0" }, @@ -14377,9 +11283,8 @@ }, "node_modules/matcher/node_modules/escape-string-regexp": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -14389,9 +11294,8 @@ }, "node_modules/md5-hex": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz", - "integrity": "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==", "dev": true, + "license": "MIT", "dependencies": { "blueimp-md5": "^2.10.0" }, @@ -14401,47 +11305,30 @@ }, "node_modules/mdurl": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==" + "license": "MIT" }, - "node_modules/mem": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/mem/-/mem-9.0.2.tgz", - "integrity": "sha512-F2t4YIv9XQUBHt6AOJ0y7lSmP1+cY7Fm1DRh9GClTGzKST7UWLMx6ly9WZdLH/G/ppM5RL4MlQfRT71ri9t19A==", + "node_modules/memoize": { + "version": "10.0.0", "dev": true, + "license": "MIT", "dependencies": { - "map-age-cleaner": "^0.1.3", - "mimic-fn": "^4.0.0" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sindresorhus/mem?sponsor=1" - } - }, - "node_modules/mem/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sindresorhus/memoize?sponsor=1" } }, "node_modules/merge-stream": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", "engines": { "node": ">= 8" } @@ -14460,9 +11347,8 @@ }, "node_modules/mime": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", "dev": true, + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -14472,18 +11358,16 @@ }, "node_modules/mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -14493,17 +11377,27 @@ }, "node_modules/mimic-fn": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "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, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -14513,13 +11407,11 @@ }, "node_modules/minimist": { "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + "license": "MIT" }, "node_modules/minipass": { "version": "3.3.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.5.tgz", - "integrity": "sha512-rQ/p+KfKBkeNwo04U15i+hOwoVBVmekmm/HcfTkTN2t9pbQKCMm4eN5gFeqgrrSp/kH/7BYYhTIHOxGqzbBPaA==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -14529,9 +11421,8 @@ }, "node_modules/minipass-collect": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", "dev": true, + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -14541,9 +11432,8 @@ }, "node_modules/minipass-fetch": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", "dev": true, + "license": "MIT", "dependencies": { "minipass": "^3.1.0", "minipass-sized": "^1.0.3", @@ -14558,8 +11448,7 @@ }, "node_modules/minipass-flush": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -14569,8 +11458,8 @@ }, "node_modules/minipass-json-stream": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", - "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "dev": true, + "license": "MIT", "dependencies": { "jsonparse": "^1.3.1", "minipass": "^3.0.0" @@ -14578,8 +11467,7 @@ }, "node_modules/minipass-pipeline": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -14589,8 +11477,7 @@ }, "node_modules/minipass-sized": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -14600,13 +11487,11 @@ }, "node_modules/minipass/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "node_modules/minizlib": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" @@ -14617,13 +11502,11 @@ }, "node_modules/minizlib/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "node_modules/mkdirp": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" }, @@ -14633,9 +11516,8 @@ }, "node_modules/mkdirp-infer-owner": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz", - "integrity": "sha512-sdqtiFt3lkOaYvTXSRIUjkIdPTcxgv5+fgqYE/5qgwdw12cOrAuzzgzvVExIkH/ul1oeHN3bCLOWSG3XOqbKKw==", "dev": true, + "license": "ISC", "dependencies": { "chownr": "^2.0.0", "infer-owner": "^1.0.4", @@ -14647,91 +11529,134 @@ }, "node_modules/mkdirp-infer-owner/node_modules/chownr": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/module-definition": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/module-definition/-/module-definition-3.3.1.tgz", - "integrity": "sha512-kLidGPwQ2yq484nSD+D3JoJp4Etc0Ox9P0L34Pu/cU4X4HcG7k7p62XI5BBuvURWMRX3RPyuhOcBHbKus+UH4A==", + "version": "5.0.1", "dev": true, + "license": "MIT", "dependencies": { - "ast-module-types": "^2.7.1", - "node-source-walk": "^4.0.0" + "ast-module-types": "^5.0.0", + "node-source-walk": "^6.0.1" }, "bin": { - "module-definition": "bin/module-definition.js" + "module-definition": "bin/cli.js" }, "engines": { - "node": ">=6.0" + "node": ">=14" } }, "node_modules/module-lookup-amd": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/module-lookup-amd/-/module-lookup-amd-7.0.1.tgz", - "integrity": "sha512-w9mCNlj0S8qviuHzpakaLVc+/7q50jl9a/kmJ/n8bmXQZgDPkQHnPBb8MUOYh3WpAYkXuNc2c+khsozhIp/amQ==", + "version": "8.0.5", "dev": true, + "license": "MIT", "dependencies": { - "commander": "^2.8.1", - "debug": "^4.1.0", - "glob": "^7.1.6", - "requirejs": "^2.3.5", + "commander": "^10.0.1", + "glob": "^7.2.3", + "requirejs": "^2.3.6", "requirejs-config-file": "^4.0.0" }, "bin": { "lookup-amd": "bin/cli.js" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" } }, "node_modules/module-lookup-amd/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "version": "10.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } }, "node_modules/moment": { "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, "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==" + "license": "MIT" + }, + "node_modules/multimatch": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "array-differ": "^4.0.0", + "array-union": "^3.0.1", + "minimatch": "^9.0.3" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/multimatch/node_modules/array-union": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/multimatch/node_modules/brace-expansion": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/multimatch/node_modules/minimatch": { + "version": "9.0.5", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/mustache": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "license": "MIT", "bin": { "mustache": "bin/mustache" } }, "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + "version": "1.0.0", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } }, "node_modules/nan": { "version": "2.18.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", - "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", + "license": "MIT", "optional": true }, "node_modules/nanoid": { "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, "funding": [ { @@ -14739,6 +11664,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -14748,29 +11674,25 @@ }, "node_modules/natural-compare": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/negotiator": { "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/neo-async": { "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/new-github-release-url": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/new-github-release-url/-/new-github-release-url-2.0.0.tgz", - "integrity": "sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^2.5.1" }, @@ -14783,9 +11705,8 @@ }, "node_modules/new-github-release-url/node_modules/type-fest": { "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=12.20" }, @@ -14793,16 +11714,8 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-cleanup": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", - "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", - "dev": true - }, "node_modules/node-domexception": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", "dev": true, "funding": [ { @@ -14814,15 +11727,34 @@ "url": "https://paypal.me/jimmywarting" } ], + "license": "MIT", "engines": { "node": ">=10.5.0" } }, + "node_modules/node-fetch": { + "version": "2.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-gyp": { "version": "9.3.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.0.tgz", - "integrity": "sha512-A6rJWfXFz7TQNjpldJ915WFb1LnhO4lIve3ANPbWreuEoLoKlFT3sxIepPBkLhM27crW8YmN+pjlgbasH6cH/Q==", "dev": true, + "license": "MIT", "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", @@ -14842,11 +11774,20 @@ "node": "^12.22 || ^14.13 || >=16" } }, + "node_modules/node-gyp-build": { + "version": "4.8.1", + "dev": true, + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, "node_modules/node-gyp/node_modules/are-we-there-yet": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", "dev": true, + "license": "ISC", "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" @@ -14857,9 +11798,8 @@ }, "node_modules/node-gyp/node_modules/gauge": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", "dev": true, + "license": "ISC", "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.3", @@ -14876,9 +11816,8 @@ }, "node_modules/node-gyp/node_modules/nopt": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", "dev": true, + "license": "ISC", "dependencies": { "abbrev": "^1.0.0" }, @@ -14891,9 +11830,8 @@ }, "node_modules/node-gyp/node_modules/npmlog": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", "dev": true, + "license": "ISC", "dependencies": { "are-we-there-yet": "^3.0.0", "console-control-strings": "^1.1.0", @@ -14904,25 +11842,10 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/node-gyp/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==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/node-gyp/node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -14935,74 +11858,75 @@ }, "node_modules/node-int64": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-releases": { "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-source-walk": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/node-source-walk/-/node-source-walk-4.2.0.tgz", - "integrity": "sha512-hPs/QMe6zS94f5+jG3kk9E7TNm4P2SulrKiLWMzKszBfNZvL/V6wseHlTd7IvfW0NZWqPtK3+9yYNr+3USGteA==", + "version": "6.0.2", "dev": true, + "license": "MIT", "dependencies": { - "@babel/parser": "^7.0.0" + "@babel/parser": "^7.21.8" }, "engines": { - "node": ">=6.0" + "node": ">=14" } }, "node_modules/nofilter": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", - "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.19" } }, "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, + "license": "MIT", "dependencies": { "abbrev": "1" }, "bin": { "nopt": "bin/nopt.js" + } + }, + "node_modules/normalize-package-data": { + "version": "6.0.2", + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" }, "engines": { - "node": "*" + "node": "^16.14.0 || >=18.0.0" } }, "node_modules/normalize-path": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/npm-bundled": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", - "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", "dev": true, + "license": "ISC", "dependencies": { "npm-normalize-package-bin": "^1.0.1" } }, "node_modules/npm-install-checks": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", - "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", + "license": "BSD-2-Clause", "dependencies": { "semver": "^7.1.1" }, @@ -15011,16 +11935,16 @@ } }, "node_modules/npm-lockfile": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/npm-lockfile/-/npm-lockfile-3.0.4.tgz", - "integrity": "sha512-IJQU7kkge0BESQDQByB+xOtAwI2Ni6UVlf019yI6VQ26A8sUthlNwnHtHyLbWfYwynoQiEOujwRemsA/hJPUXw==", + "version": "3.0.7", "dev": true, + "license": "MIT", "dependencies": { "@npmcli/arborist": "=5.2.1", "colors": "=1.4.0", "find-package-json": "^1.2.0", - "object-inspect": "^1.12.2", - "yargs": "^17.5.1" + "object-inspect": "^1.12.3", + "pacote": "=13.6.0", + "yargs": "^17.7.2" }, "bin": { "npm-lockfile": "bin.js" @@ -15034,9 +11958,8 @@ }, "node_modules/npm-lockfile/node_modules/@npmcli/arborist": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-5.2.1.tgz", - "integrity": "sha512-DNyTHov3lU7PtCGHABzrPqQOUiBdiYzZ5dLv3D0RD5I9KbmhTLcZI/rv3ddZY0K9vpDE/R+R48b+cU/dUkL0Tw==", "dev": true, + "license": "ISC", "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/installed-package-contents": "^1.0.7", @@ -15082,9 +12005,8 @@ }, "node_modules/npm-lockfile/node_modules/@npmcli/git": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-3.0.2.tgz", - "integrity": "sha512-CAcd08y3DWBJqJDpfuVL0uijlq5oaXaOJEKHKc4wqrjd00gkvTZB+nFuLn+doOOKddaQS9JfqtNoFCO2LCvA3w==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/promise-spawn": "^3.0.0", "lru-cache": "^7.4.4", @@ -15102,9 +12024,8 @@ }, "node_modules/npm-lockfile/node_modules/@npmcli/move-file": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", "dev": true, + "license": "MIT", "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" @@ -15115,9 +12036,8 @@ }, "node_modules/npm-lockfile/node_modules/@npmcli/promise-spawn": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-3.0.0.tgz", - "integrity": "sha512-s9SgS+p3a9Eohe68cSI3fi+hpcZUmXq5P7w0kMlAsWVtR7XbK3ptkZqKT2cK1zLDObJ3sR+8P59sJE0w/KTL1g==", "dev": true, + "license": "ISC", "dependencies": { "infer-owner": "^1.0.4" }, @@ -15127,9 +12047,8 @@ }, "node_modules/npm-lockfile/node_modules/@npmcli/run-script": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-3.0.3.tgz", - "integrity": "sha512-ZXL6qgC5NjwfZJ2nET+ZSLEz/PJgJ/5CU90C2S66dZY4Jw73DasS4ZCXuy/KHWYP0imjJ4VtA+Gebb5BxxKp9Q==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/node-gyp": "^2.0.0", "@npmcli/promise-spawn": "^3.0.0", @@ -15142,9 +12061,8 @@ }, "node_modules/npm-lockfile/node_modules/are-we-there-yet": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", "dev": true, + "license": "ISC", "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" @@ -15155,41 +12073,24 @@ }, "node_modules/npm-lockfile/node_modules/builtins": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.0.0" } }, "node_modules/npm-lockfile/node_modules/chownr": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, - "node_modules/npm-lockfile/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/npm-lockfile/node_modules/gauge": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", "dev": true, + "license": "ISC", "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.3", @@ -15206,9 +12107,8 @@ }, "node_modules/npm-lockfile/node_modules/hosted-git-info": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz", - "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^7.5.1" }, @@ -15218,9 +12118,8 @@ }, "node_modules/npm-lockfile/node_modules/http-proxy-agent": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", "dev": true, + "license": "MIT", "dependencies": { "@tootallnate/once": "1", "agent-base": "6", @@ -15232,18 +12131,16 @@ }, "node_modules/npm-lockfile/node_modules/lru-cache": { "version": "7.14.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz", - "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } }, "node_modules/npm-lockfile/node_modules/node-gyp": { "version": "8.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", - "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", "dev": true, + "license": "MIT", "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", @@ -15265,9 +12162,8 @@ }, "node_modules/npm-lockfile/node_modules/node-gyp/node_modules/@npmcli/move-file": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", "dev": true, + "license": "MIT", "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" @@ -15278,9 +12174,8 @@ }, "node_modules/npm-lockfile/node_modules/node-gyp/node_modules/cacache": { "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/fs": "^1.0.0", "@npmcli/move-file": "^1.0.1", @@ -15307,9 +12202,8 @@ }, "node_modules/npm-lockfile/node_modules/node-gyp/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -15319,9 +12213,8 @@ }, "node_modules/npm-lockfile/node_modules/node-gyp/node_modules/make-fetch-happen": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", "dev": true, + "license": "ISC", "dependencies": { "agentkeepalive": "^4.1.3", "cacache": "^15.2.0", @@ -15346,9 +12239,8 @@ }, "node_modules/npm-lockfile/node_modules/node-gyp/node_modules/ssri": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", "dev": true, + "license": "ISC", "dependencies": { "minipass": "^3.1.1" }, @@ -15358,9 +12250,8 @@ }, "node_modules/npm-lockfile/node_modules/nopt": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "dev": true, + "license": "ISC", "dependencies": { "abbrev": "1" }, @@ -15373,9 +12264,8 @@ }, "node_modules/npm-lockfile/node_modules/npm-install-checks": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-5.0.0.tgz", - "integrity": "sha512-65lUsMI8ztHCxFz5ckCEC44DRvEGdZX5usQFriauxHEwt7upv1FKaQEmAtU0YnOAdwuNWCmk64xYiQABNrEyLA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "semver": "^7.1.1" }, @@ -15385,9 +12275,8 @@ }, "node_modules/npm-lockfile/node_modules/npm-package-arg": { "version": "9.1.2", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", - "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", "dev": true, + "license": "ISC", "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -15400,9 +12289,8 @@ }, "node_modules/npm-lockfile/node_modules/npm-registry-fetch": { "version": "13.3.1", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-13.3.1.tgz", - "integrity": "sha512-eukJPi++DKRTjSBRcDZSDDsGqRK3ehbxfFUcgaRd0Yp6kRwOwh2WVn0r+8rMB4nnuzvAk6rQVzl6K5CkYOmnvw==", "dev": true, + "license": "ISC", "dependencies": { "make-fetch-happen": "^10.0.6", "minipass": "^3.1.6", @@ -15418,9 +12306,8 @@ }, "node_modules/npm-lockfile/node_modules/npm-registry-fetch/node_modules/minipass-fetch": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", "dev": true, + "license": "MIT", "dependencies": { "minipass": "^3.1.6", "minipass-sized": "^1.0.3", @@ -15435,9 +12322,8 @@ }, "node_modules/npm-lockfile/node_modules/npmlog": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", "dev": true, + "license": "ISC", "dependencies": { "are-we-there-yet": "^3.0.0", "console-control-strings": "^1.1.0", @@ -15449,15 +12335,14 @@ } }, "node_modules/npm-lockfile/node_modules/pacote": { - "version": "13.6.2", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-13.6.2.tgz", - "integrity": "sha512-Gu8fU3GsvOPkak2CkbojR7vjs3k3P9cA6uazKTHdsdV0gpCEQq2opelnEv30KRQWgVzP5Vd/5umjcedma3MKtg==", + "version": "13.6.0", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/git": "^3.0.0", "@npmcli/installed-package-contents": "^1.0.7", "@npmcli/promise-spawn": "^3.0.0", - "@npmcli/run-script": "^4.1.0", + "@npmcli/run-script": "^3.0.1", "cacache": "^16.0.0", "chownr": "^2.0.0", "fs-minipass": "^2.1.0", @@ -15483,108 +12368,36 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/npm-lockfile/node_modules/pacote/node_modules/@npmcli/run-script": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-4.2.1.tgz", - "integrity": "sha512-7dqywvVudPSrRCW5nTHpHgeWnbBtz8cFkOuKrecm6ih+oO9ciydhWt6OF7HlqupRRmB8Q/gECVdB9LMfToJbRg==", + "node_modules/npm-lockfile/node_modules/read-package-json-fast": { + "version": "2.0.3", "dev": true, + "license": "ISC", "dependencies": { - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/promise-spawn": "^3.0.0", - "node-gyp": "^9.0.0", - "read-package-json-fast": "^2.0.3", - "which": "^2.0.2" + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=10" } }, - "node_modules/npm-lockfile/node_modules/pacote/node_modules/node-gyp": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.0.tgz", - "integrity": "sha512-A6rJWfXFz7TQNjpldJ915WFb1LnhO4lIve3ANPbWreuEoLoKlFT3sxIepPBkLhM27crW8YmN+pjlgbasH6cH/Q==", + "node_modules/npm-lockfile/node_modules/rimraf": { + "version": "3.0.2", "dev": true, + "license": "ISC", "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" + "glob": "^7.1.3" }, "bin": { - "node-gyp": "bin/node-gyp.js" + "rimraf": "bin.js" }, - "engines": { - "node": "^12.22 || ^14.13 || >=16" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/npm-lockfile/node_modules/pacote/node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm-lockfile/node_modules/read-package-json-fast": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", - "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", - "dev": true, - "dependencies": { - "json-parse-even-better-errors": "^2.3.0", - "npm-normalize-package-bin": "^1.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm-lockfile/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==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/npm-lockfile/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm-lockfile/node_modules/socks-proxy-agent": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", - "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "node_modules/npm-lockfile/node_modules/socks-proxy-agent": { + "version": "6.2.1", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", @@ -15596,9 +12409,8 @@ }, "node_modules/npm-lockfile/node_modules/validate-npm-package-name": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz", - "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", "dev": true, + "license": "ISC", "dependencies": { "builtins": "^5.0.0" }, @@ -15606,59 +12418,40 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/npm-lockfile/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/npm-lockfile/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, - "node_modules/npm-lockfile/node_modules/yargs": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", - "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", + "node_modules/npm-normalize-package-bin": { + "version": "1.0.1", "dev": true, + "license": "ISC" + }, + "node_modules/npm-package-arg": { + "version": "11.0.2", + "license": "ISC", "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.0.0" + "hosted-git-info": "^7.0.0", + "proc-log": "^4.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" }, "engines": { - "node": ">=12" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/npm-lockfile/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, + "node_modules/npm-package-arg/node_modules/proc-log": { + "version": "4.2.0", + "license": "ISC", "engines": { - "node": ">=12" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", - "dev": true - }, "node_modules/npm-packlist": { "version": "5.1.3", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.3.tgz", - "integrity": "sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^8.0.1", "ignore-walk": "^5.0.1", @@ -15674,18 +12467,16 @@ }, "node_modules/npm-packlist/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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/npm-packlist/node_modules/glob": { "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -15702,9 +12493,8 @@ }, "node_modules/npm-packlist/node_modules/ignore-walk": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz", - "integrity": "sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==", "dev": true, + "license": "ISC", "dependencies": { "minimatch": "^5.0.1" }, @@ -15714,9 +12504,8 @@ }, "node_modules/npm-packlist/node_modules/minimatch": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -15726,9 +12515,8 @@ }, "node_modules/npm-packlist/node_modules/npm-bundled": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-2.0.1.tgz", - "integrity": "sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==", "dev": true, + "license": "ISC", "dependencies": { "npm-normalize-package-bin": "^2.0.0" }, @@ -15738,18 +12526,16 @@ }, "node_modules/npm-packlist/node_modules/npm-normalize-package-bin": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", - "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", "dev": true, + "license": "ISC", "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm-pick-manifest": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-7.0.2.tgz", - "integrity": "sha512-gk37SyRmlIjvTfcYl6RzDbSmS9Y4TOBXfsPnoYqTHARNgWbyDiCSMLUpmALDj4jjcTZpURiEfsSHJj9k7EV4Rw==", "dev": true, + "license": "ISC", "dependencies": { "npm-install-checks": "^5.0.0", "npm-normalize-package-bin": "^2.0.0", @@ -15762,18 +12548,16 @@ }, "node_modules/npm-pick-manifest/node_modules/builtins": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.0.0" } }, "node_modules/npm-pick-manifest/node_modules/hosted-git-info": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz", - "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^7.5.1" }, @@ -15783,18 +12567,16 @@ }, "node_modules/npm-pick-manifest/node_modules/lru-cache": { "version": "7.14.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz", - "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } }, "node_modules/npm-pick-manifest/node_modules/npm-install-checks": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-5.0.0.tgz", - "integrity": "sha512-65lUsMI8ztHCxFz5ckCEC44DRvEGdZX5usQFriauxHEwt7upv1FKaQEmAtU0YnOAdwuNWCmk64xYiQABNrEyLA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "semver": "^7.1.1" }, @@ -15804,18 +12586,16 @@ }, "node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", - "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", "dev": true, + "license": "ISC", "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm-pick-manifest/node_modules/npm-package-arg": { "version": "9.1.2", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", - "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", "dev": true, + "license": "ISC", "dependencies": { "hosted-git-info": "^5.0.0", "proc-log": "^2.0.1", @@ -15828,9 +12608,8 @@ }, "node_modules/npm-pick-manifest/node_modules/validate-npm-package-name": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz", - "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", "dev": true, + "license": "ISC", "dependencies": { "builtins": "^5.0.0" }, @@ -15839,26 +12618,25 @@ } }, "node_modules/npm-registry-fetch": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-16.1.0.tgz", - "integrity": "sha512-PQCELXKt8Azvxnt5Y85GseQDJJlglTFM9L9U9gkv2y4e9s0k3GVDdOx3YoB6gm2Do0hlkzC39iCGXby+Wve1Bw==", + "version": "17.1.0", + "license": "ISC", "dependencies": { + "@npmcli/redact": "^2.0.0", + "jsonparse": "^1.3.1", "make-fetch-happen": "^13.0.0", "minipass": "^7.0.2", "minipass-fetch": "^3.0.0", - "minipass-json-stream": "^1.0.1", "minizlib": "^2.1.2", "npm-package-arg": "^11.0.0", - "proc-log": "^3.0.0" + "proc-log": "^4.0.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm-registry-fetch/node_modules/@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "version": "3.1.1", + "license": "ISC", "dependencies": { "semver": "^7.3.5" }, @@ -15868,24 +12646,14 @@ }, "node_modules/npm-registry-fetch/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==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, - "node_modules/npm-registry-fetch/node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dependencies": { - "semver": "^7.0.0" - } - }, "node_modules/npm-registry-fetch/node_modules/cacache": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", - "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", + "version": "18.0.3", + "license": "ISC", "dependencies": { "@npmcli/fs": "^3.1.0", "fs-minipass": "^3.0.0", @@ -15906,8 +12674,7 @@ }, "node_modules/npm-registry-fetch/node_modules/fs-minipass": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -15916,41 +12683,45 @@ } }, "node_modules/npm-registry-fetch/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.4.2", + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/npm-registry-fetch/node_modules/hosted-git-info": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", - "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", + "node_modules/npm-registry-fetch/node_modules/jackspeak": { + "version": "3.4.0", + "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^10.0.1" + "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", - "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", + "version": "13.0.1", + "license": "ISC", "dependencies": { "@npmcli/agent": "^2.0.0", "cacache": "^18.0.0", @@ -15961,6 +12732,7 @@ "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", + "proc-log": "^4.2.0", "promise-retry": "^2.0.1", "ssri": "^10.0.0" }, @@ -15969,9 +12741,8 @@ } }, "node_modules/npm-registry-fetch/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.5", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -15983,17 +12754,15 @@ } }, "node_modules/npm-registry-fetch/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.2", + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/npm-registry-fetch/node_modules/minipass-collect": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -16002,9 +12771,8 @@ } }, "node_modules/npm-registry-fetch/node_modules/minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "version": "3.0.5", + "license": "MIT", "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", @@ -16017,32 +12785,16 @@ "encoding": "^0.1.13" } }, - "node_modules/npm-registry-fetch/node_modules/npm-package-arg": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", - "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", - "dependencies": { - "hosted-git-info": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, "node_modules/npm-registry-fetch/node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "version": "4.2.0", + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/npm-registry-fetch/node_modules/ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "version": "10.0.6", + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -16052,8 +12804,7 @@ }, "node_modules/npm-registry-fetch/node_modules/unique-filename": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "license": "ISC", "dependencies": { "unique-slug": "^4.0.0" }, @@ -16063,8 +12814,7 @@ }, "node_modules/npm-registry-fetch/node_modules/unique-slug": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, @@ -16072,22 +12822,10 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/npm-registry-fetch/node_modules/validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", - "dependencies": { - "builtins": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/npm-run-path": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.0.0" }, @@ -16095,43 +12833,34 @@ "node": ">=8" } }, - "node_modules/npmlog": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-7.0.1.tgz", - "integrity": "sha512-uJ0YFk/mCQpLBt+bxN88AKd+gyqZvZDbtiNxk6Waqcj2aPRyfVx8ITawkyQynxUagInjdYT1+qj4NfA5KJJUxg==", + "node_modules/object-assign": { + "version": "4.1.1", "dev": true, - "dependencies": { - "are-we-there-yet": "^4.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^5.0.0", - "set-blocking": "^2.0.0" - }, + "license": "MIT", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=0.10.0" } }, "node_modules/object-inspect": { "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "license": "ISC", "dependencies": { "wrappy": "1" } }, "node_modules/onetime": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, @@ -16144,24 +12873,22 @@ }, "node_modules/opener": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "license": "(WTFPL OR MIT)", "bin": { "opener": "bin/opener-bin.js" } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.4", "dev": true, + "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -16169,9 +12896,8 @@ }, "node_modules/ora": { "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, + "license": "MIT", "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", @@ -16192,55 +12918,43 @@ }, "node_modules/os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-event": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-5.0.1.tgz", - "integrity": "sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==", - "dev": true, + "node_modules/p-limit": { + "version": "3.1.0", + "license": "MIT", "dependencies": { - "p-timeout": "^5.0.2" + "yocto-queue": "^0.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-event/node_modules/p-timeout": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", - "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==", - "dev": true, + "node_modules/p-locate": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/p-map": { + "version": "4.0.0", + "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" + "aggregate-error": "^3.0.0" }, "engines": { "node": ">=10" @@ -16249,29 +12963,27 @@ "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==", + "node_modules/p-queue": { + "version": "8.0.1", + "dev": true, + "license": "MIT", "dependencies": { - "p-limit": "^3.0.2" + "eventemitter3": "^5.0.1", + "p-timeout": "^6.1.2" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dependencies": { - "aggregate-error": "^3.0.0" - }, + "node_modules/p-timeout": { + "version": "6.1.2", + "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -16279,47 +12991,63 @@ }, "node_modules/p-try": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/package-config": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up-simple": "^1.0.0", + "load-json-file": "^7.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "license": "BlueOak-1.0.0" + }, "node_modules/pacote": { - "version": "17.0.6", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-17.0.6.tgz", - "integrity": "sha512-cJKrW21VRE8vVTRskJo78c/RCvwJCn1f4qgfxL4w77SOWrTCRcmfkYHlHtS0gqpgjv3zhXflRtgsrUCX5xwNnQ==", + "version": "18.0.6", + "license": "ISC", "dependencies": { "@npmcli/git": "^5.0.0", "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/package-json": "^5.1.0", "@npmcli/promise-spawn": "^7.0.0", - "@npmcli/run-script": "^7.0.0", + "@npmcli/run-script": "^8.0.0", "cacache": "^18.0.0", "fs-minipass": "^3.0.0", "minipass": "^7.0.2", "npm-package-arg": "^11.0.0", "npm-packlist": "^8.0.0", "npm-pick-manifest": "^9.0.0", - "npm-registry-fetch": "^16.0.0", - "proc-log": "^3.0.0", + "npm-registry-fetch": "^17.0.0", + "proc-log": "^4.0.0", "promise-retry": "^2.0.1", - "read-package-json": "^7.0.0", - "read-package-json-fast": "^3.0.0", "sigstore": "^2.2.0", "ssri": "^10.0.0", "tar": "^6.1.11" }, "bin": { - "pacote": "lib/bin.js" + "pacote": "bin/index.js" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/pacote/node_modules/@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "version": "3.1.1", + "license": "ISC", "dependencies": { "semver": "^7.3.5" }, @@ -16329,8 +13057,7 @@ }, "node_modules/pacote/node_modules/@npmcli/installed-package-contents": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", - "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", + "license": "ISC", "dependencies": { "npm-bundled": "^3.0.0", "npm-normalize-package-bin": "^3.0.0" @@ -16344,23 +13071,21 @@ }, "node_modules/pacote/node_modules/@npmcli/node-gyp": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", - "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/pacote/node_modules/@npmcli/package-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.0.0.tgz", - "integrity": "sha512-OI2zdYBLhQ7kpNPaJxiflofYIpkNLi+lnGdzqUOfRmCF3r2l1nadcjtCYMJKv/Utm/ZtlffaUuTiAktPHbc17g==", + "version": "5.2.0", + "license": "ISC", "dependencies": { "@npmcli/git": "^5.0.0", "glob": "^10.2.2", "hosted-git-info": "^7.0.0", "json-parse-even-better-errors": "^3.0.0", "normalize-package-data": "^6.0.0", - "proc-log": "^3.0.0", + "proc-log": "^4.0.0", "semver": "^7.5.3" }, "engines": { @@ -16368,14 +13093,14 @@ } }, "node_modules/pacote/node_modules/@npmcli/run-script": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-7.0.4.tgz", - "integrity": "sha512-9ApYM/3+rBt9V80aYg6tZfzj3UWdiYyCt7gJUD1VJKvWF5nwKDSICXbYIQbspFTq6TOpbsEtIC0LArB8d9PFmg==", + "version": "8.1.0", + "license": "ISC", "dependencies": { "@npmcli/node-gyp": "^3.0.0", "@npmcli/package-json": "^5.0.0", "@npmcli/promise-spawn": "^7.0.0", "node-gyp": "^10.0.0", + "proc-log": "^4.0.0", "which": "^4.0.0" }, "engines": { @@ -16384,32 +13109,21 @@ }, "node_modules/pacote/node_modules/abbrev": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/pacote/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==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, - "node_modules/pacote/node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dependencies": { - "semver": "^7.0.0" - } - }, "node_modules/pacote/node_modules/cacache": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", - "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", + "version": "18.0.3", + "license": "ISC", "dependencies": { "@npmcli/fs": "^3.1.0", "fs-minipass": "^3.0.0", @@ -16430,8 +13144,7 @@ }, "node_modules/pacote/node_modules/fs-minipass": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -16440,57 +13153,59 @@ } }, "node_modules/pacote/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.4.2", + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/pacote/node_modules/hosted-git-info": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", - "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, "node_modules/pacote/node_modules/isexe": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "license": "ISC", "engines": { "node": ">=16" } }, + "node_modules/pacote/node_modules/jackspeak": { + "version": "3.4.0", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/pacote/node_modules/json-parse-even-better-errors": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", - "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", + "version": "3.0.2", + "license": "MIT", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/pacote/node_modules/make-fetch-happen": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", - "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", + "version": "13.0.1", + "license": "ISC", "dependencies": { "@npmcli/agent": "^2.0.0", "cacache": "^18.0.0", @@ -16501,6 +13216,7 @@ "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", + "proc-log": "^4.2.0", "promise-retry": "^2.0.1", "ssri": "^10.0.0" }, @@ -16509,9 +13225,8 @@ } }, "node_modules/pacote/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.5", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -16523,17 +13238,15 @@ } }, "node_modules/pacote/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.2", + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/pacote/node_modules/minipass-collect": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -16542,9 +13255,8 @@ } }, "node_modules/pacote/node_modules/minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "version": "3.0.5", + "license": "MIT", "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", @@ -16558,9 +13270,8 @@ } }, "node_modules/pacote/node_modules/node-gyp": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz", - "integrity": "sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==", + "version": "10.1.0", + "license": "MIT", "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", @@ -16580,10 +13291,16 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/pacote/node_modules/node-gyp/node_modules/proc-log": { + "version": "3.0.0", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/pacote/node_modules/nopt": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", - "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", + "version": "7.2.1", + "license": "ISC", "dependencies": { "abbrev": "^2.0.0" }, @@ -16594,24 +13311,9 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/pacote/node_modules/normalize-package-data": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.0.tgz", - "integrity": "sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==", - "dependencies": { - "hosted-git-info": "^7.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, "node_modules/pacote/node_modules/npm-bundled": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", - "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==", + "license": "ISC", "dependencies": { "npm-normalize-package-bin": "^3.0.0" }, @@ -16621,30 +13323,14 @@ }, "node_modules/pacote/node_modules/npm-normalize-package-bin": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/pacote/node_modules/npm-package-arg": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", - "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", - "dependencies": { - "hosted-git-info": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, "node_modules/pacote/node_modules/npm-packlist": { "version": "8.0.2", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-8.0.2.tgz", - "integrity": "sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==", + "license": "ISC", "dependencies": { "ignore-walk": "^6.0.4" }, @@ -16654,8 +13340,7 @@ }, "node_modules/pacote/node_modules/npm-pick-manifest": { "version": "9.0.0", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.0.0.tgz", - "integrity": "sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg==", + "license": "ISC", "dependencies": { "npm-install-checks": "^6.0.0", "npm-normalize-package-bin": "^3.0.0", @@ -16667,31 +13352,15 @@ } }, "node_modules/pacote/node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "version": "4.2.0", + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/pacote/node_modules/read-package-json": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-7.0.0.tgz", - "integrity": "sha512-uL4Z10OKV4p6vbdvIXB+OzhInYtIozl/VxUBPgNkBuUi2DeRonnuspmaVAMcrkmfjKGNmRndyQAbE7/AmzGwFg==", - "dependencies": { - "glob": "^10.2.2", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, "node_modules/pacote/node_modules/ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "version": "10.0.6", + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -16701,8 +13370,7 @@ }, "node_modules/pacote/node_modules/unique-filename": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "license": "ISC", "dependencies": { "unique-slug": "^4.0.0" }, @@ -16712,8 +13380,7 @@ }, "node_modules/pacote/node_modules/unique-slug": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, @@ -16721,21 +13388,9 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/pacote/node_modules/validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", - "dependencies": { - "builtins": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/pacote/node_modules/which": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "license": "ISC", "dependencies": { "isexe": "^3.1.1" }, @@ -16748,9 +13403,8 @@ }, "node_modules/parent-module": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -16760,18 +13414,16 @@ }, "node_modules/parent-module/node_modules/callsites": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/parse-conflict-json": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-2.0.2.tgz", - "integrity": "sha512-jDbRGb00TAPFsKWCpZZOT93SxVP9nONOSgES3AevqRq/CHvavEBvKAjxX9p5Y5F0RZLxH9Ufd9+RwtCsa+lFDA==", "dev": true, + "license": "ISC", "dependencies": { "json-parse-even-better-errors": "^2.3.1", "just-diff": "^5.0.1", @@ -16783,9 +13435,8 @@ }, "node_modules/parse-json": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -16801,80 +13452,64 @@ }, "node_modules/parse-ms": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", - "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/parse-path": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz", - "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==", "dev": true, + "license": "MIT", "dependencies": { "protocols": "^2.0.0" } }, "node_modules/parse-url": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz", - "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==", "dev": true, + "license": "MIT", "dependencies": { "parse-path": "^7.0.0" } }, "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==", + "license": "MIT", "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": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "license": "MIT", "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==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-parse": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -16882,40 +13517,29 @@ }, "node_modules/path-scurry/node_modules/minipass": { "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", - "dev": true, - "dependencies": { - "through": "~2.3" - } - }, "node_modules/picocolors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -16925,128 +13549,16 @@ }, "node_modules/pirates": { "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } }, - "node_modules/pkg-conf": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-4.0.0.tgz", - "integrity": "sha512-7dmgi4UY4qk+4mj5Cd8v/GExPo0K+SlY+hulOSdfZ/T6jVH6//y7NtzZo5WrfhDBxuQ0jCa7fLZmNaNh7EWL/w==", - "dev": true, - "dependencies": { - "find-up": "^6.0.0", - "load-json-file": "^7.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-conf/node_modules/find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, - "dependencies": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-conf/node_modules/load-json-file": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", - "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-conf/node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "dependencies": { - "p-locate": "^6.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-conf/node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-conf/node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, - "dependencies": { - "p-limit": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-conf/node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/pkg-conf/node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/pkg-dir": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -17056,9 +13568,8 @@ }, "node_modules/pkg-dir/node_modules/find-up": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -17069,9 +13580,8 @@ }, "node_modules/pkg-dir/node_modules/locate-path": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -17081,9 +13591,8 @@ }, "node_modules/pkg-dir/node_modules/p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -17096,9 +13605,8 @@ }, "node_modules/pkg-dir/node_modules/p-locate": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -17108,9 +13616,8 @@ }, "node_modules/plur": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/plur/-/plur-5.1.0.tgz", - "integrity": "sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==", "dev": true, + "license": "MIT", "dependencies": { "irregular-plurals": "^3.3.0" }, @@ -17123,19 +13630,16 @@ }, "node_modules/pluralize": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/popper.js": { "version": "1.16.1", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", - "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", - "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", "dev": true, + "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" @@ -17198,6 +13702,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.1", @@ -17209,9 +13714,8 @@ }, "node_modules/postcss-url": { "version": "10.1.3", - "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-10.1.3.tgz", - "integrity": "sha512-FUzyxfI5l2tKmXdYc6VTu3TWZsInayEKPbiyW+P6vmmIrrb4I6CGX0BFoewgYHLK+oIL5FECEK02REYRpBvUCw==", "dev": true, + "license": "MIT", "dependencies": { "make-dir": "~3.1.0", "mime": "~2.5.2", @@ -17227,9 +13731,8 @@ }, "node_modules/postcss-url/node_modules/minimatch": { "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -17238,94 +13741,88 @@ } }, "node_modules/postcss-values-parser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", - "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "version": "6.0.2", "dev": true, + "license": "MPL-2.0", "dependencies": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" + "color-name": "^1.1.4", + "is-url-superb": "^4.0.0", + "quote-unquote": "^1.0.0" }, "engines": { - "node": ">=6.14.4" + "node": ">=10" + }, + "peerDependencies": { + "postcss": "^8.2.9" } }, "node_modules/precinct": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/precinct/-/precinct-7.1.0.tgz", - "integrity": "sha512-I1RkW5PX51/q6Xl39//D7x9NgaKNGHpR5DCNaoxP/b2+KbzzXDNhauJUMV17KSYkJA41CSpwYUPRtRoNxbshWA==", + "version": "11.0.5", "dev": true, + "license": "MIT", "dependencies": { - "commander": "^2.20.3", - "debug": "^4.3.1", - "detective-amd": "^3.0.1", - "detective-cjs": "^3.1.1", - "detective-es6": "^2.2.0", - "detective-less": "^1.0.2", - "detective-postcss": "^4.0.0", - "detective-sass": "^3.0.1", - "detective-scss": "^2.0.1", - "detective-stylus": "^1.0.0", - "detective-typescript": "^6.0.0", - "module-definition": "^3.3.1", - "node-source-walk": "^4.2.0" + "@dependents/detective-less": "^4.1.0", + "commander": "^10.0.1", + "detective-amd": "^5.0.2", + "detective-cjs": "^5.0.1", + "detective-es6": "^4.0.1", + "detective-postcss": "^6.1.3", + "detective-sass": "^5.0.3", + "detective-scss": "^4.0.3", + "detective-stylus": "^4.0.0", + "detective-typescript": "^11.1.0", + "module-definition": "^5.0.1", + "node-source-walk": "^6.0.2" }, "bin": { "precinct": "bin/cli.js" }, "engines": { - "node": "^10.13 || ^12 || >=14" + "node": "^14.14.0 || >=16.0.0" } }, "node_modules/precinct/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/precinct/node_modules/detective-typescript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/detective-typescript/-/detective-typescript-6.0.0.tgz", - "integrity": "sha512-vTidcSDK3QostdbrH2Rwf9FhvrgJ4oIaVw5jbolgruTejexk6nNa9DShGpuS8CFVDb1IP86jct5BaZt1wSxpkA==", + "version": "10.0.1", "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "^4.8.2", - "ast-module-types": "^2.7.1", - "node-source-walk": "^4.2.0", - "typescript": "^3.9.7" - }, + "license": "MIT", "engines": { - "node": "^10.13 || >=12.0.0" + "node": ">=14" } }, - "node_modules/precinct/node_modules/typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "node_modules/prelude-ls": { + "version": "1.2.1", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">=4.2.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/pretty-ms": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", - "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==", "dev": true, + "license": "MIT", "dependencies": { "parse-ms": "^2.1.0" }, @@ -17337,9 +13834,8 @@ } }, "node_modules/prettyjson": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/prettyjson/-/prettyjson-1.2.2.tgz", - "integrity": "sha512-hDso231aQslRQPJjuSMIyUTN5CmW78AwEHlvigOs9E9IO+blW1AJTCJC6pQ8FArBSFsp5ZUdZsWXCUfXiD2D0w==", + "version": "1.2.5", + "license": "MIT", "dependencies": { "colors": "1.4.0", "minimist": "^1.2.0" @@ -17350,53 +13846,47 @@ }, "node_modules/proc-log": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz", - "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==", + "dev": true, + "license": "ISC", "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/progress": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/promise-all-reject-late": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz", - "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==", "dev": true, + "license": "ISC", "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/promise-call-limit": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-1.0.1.tgz", - "integrity": "sha512-3+hgaa19jzCGLuSCbieeRsu5C2joKfYn8pY6JAuXFRVfF4IO+L7UPpFWNTeWT9pM7uhskvbPPd/oEOktCn317Q==", "dev": true, + "license": "ISC", "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/promise-inflight": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + "license": "ISC" }, "node_modules/promise-polyfill": { "version": "1.1.6", - "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-1.1.6.tgz", - "integrity": "sha512-7rrONfyLkDEc7OJ5QBkqa4KI4EBhCd340xRuIUPGCfu13znS+vx+VDdrT9ODAJHlXm7w4lbxN3DRjyv58EuzDg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/promise-retry": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" @@ -17407,9 +13897,8 @@ }, "node_modules/prompts": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, + "license": "MIT", "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" @@ -17420,52 +13909,31 @@ }, "node_modules/proto-list": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/protocols": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", - "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==", - "dev": true - }, - "node_modules/ps-tree": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", - "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", "dev": true, - "dependencies": { - "event-stream": "=3.3.4" - }, - "bin": { - "ps-tree": "bin/ps-tree.js" - }, - "engines": { - "node": ">= 0.10" - } + "license": "MIT" }, "node_modules/punycode": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/punycode.js": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/pure-rand": { "version": "6.0.4", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", - "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", "dev": true, "funding": [ { @@ -17476,7 +13944,8 @@ "type": "opencollective", "url": "https://opencollective.com/fast-check" } - ] + ], + "license": "MIT" }, "node_modules/qs": { "version": "6.13.0", @@ -17496,8 +13965,6 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "funding": [ { "type": "github", @@ -17511,13 +13978,18 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" + }, + "node_modules/quote-unquote": { + "version": "1.0.0", + "dev": true, + "license": "MIT" }, "node_modules/rc": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -17530,38 +14002,38 @@ }, "node_modules/rc/node_modules/strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/react-is": { + "version": "18.3.1", + "license": "MIT" + }, "node_modules/read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "version": "3.0.1", + "license": "ISC", "dependencies": { - "mute-stream": "~0.0.4" + "mute-stream": "^1.0.0" }, "engines": { - "node": ">=0.8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/read-cmd-shim": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-3.0.1.tgz", - "integrity": "sha512-kEmDUoYf/CDy8yZbLTmhB1X9kkjf9Q80PCNsDMb7ufrGd6zZSQA1+UyjrO+pZm5K/S4OXCWJeiIt1JA8kAsa6g==", "dev": true, + "license": "ISC", "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/read-package-json": { "version": "5.0.2", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-5.0.2.tgz", - "integrity": "sha512-BSzugrt4kQ/Z0krro8zhTwV1Kd79ue25IhNN/VtHFy1mG/6Tluyi+msc0UpwaoQzxSHa28mntAjIZY6kEgfR9Q==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^8.0.1", "json-parse-even-better-errors": "^2.3.1", @@ -17572,48 +14044,18 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/read-package-json-fast": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", - "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", - "dependencies": { - "json-parse-even-better-errors": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", - "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/read-package-json-fast/node_modules/npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/read-package-json/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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/read-package-json/node_modules/glob": { "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -17630,9 +14072,8 @@ }, "node_modules/read-package-json/node_modules/hosted-git-info": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz", - "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^7.5.1" }, @@ -17642,18 +14083,16 @@ }, "node_modules/read-package-json/node_modules/lru-cache": { "version": "7.14.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz", - "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } }, "node_modules/read-package-json/node_modules/minimatch": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -17663,9 +14102,8 @@ }, "node_modules/read-package-json/node_modules/normalize-package-data": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", - "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^5.0.0", "is-core-module": "^2.8.1", @@ -17678,68 +14116,90 @@ }, "node_modules/read-package-json/node_modules/npm-normalize-package-bin": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", - "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", "dev": true, + "license": "ISC", "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/readdir-scoped-modules": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", - "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", + "node_modules/read-pkg": { + "version": "9.0.1", "dev": true, + "license": "MIT", "dependencies": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/read-pkg/node_modules/parse-json": { + "version": "8.1.0", "dev": true, + "license": "MIT", "dependencies": { - "picomatch": "^2.2.1" + "@babel/code-frame": "^7.22.13", + "index-to-position": "^0.1.2", + "type-fest": "^4.7.1" }, "engines": { - "node": ">=8.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/readline-sync": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", - "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==", + "node_modules/read-pkg/node_modules/type-fest": { + "version": "4.20.1", + "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">= 0.8.0" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", - "dev": true - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "node_modules/readable-stream": { + "version": "3.6.2", "dev": true, - "engines": { - "node": ">=8" + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-scoped-modules": { + "version": "1.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" } }, + "node_modules/regenerator-runtime": { + "version": "0.14.0", + "dev": true, + "license": "MIT" + }, "node_modules/rename-overwrite": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/rename-overwrite/-/rename-overwrite-4.0.3.tgz", - "integrity": "sha512-e1zOWZh4Lauz5DcLMC8j4eoOHPIrZkAVpiocE9SkDE1ZrGMW+W88LR1Y2YjD1DFgOYfJWqSsK6JKsRfuRH+tbQ==", + "version": "5.0.0", "dev": true, + "license": "MIT", "dependencies": { "@zkochan/rimraf": "^2.1.2", "fs-extra": "10.1.0" @@ -17750,9 +14210,8 @@ }, "node_modules/rename-overwrite/node_modules/fs-extra": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -17762,45 +14221,31 @@ "node": ">=12" } }, - "node_modules/rename-overwrite/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/repeat-string": { "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "license": "MIT", "engines": { "node": ">=0.10" } }, "node_modules/require-directory": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/require-main-filename": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + "dev": true, + "license": "ISC" }, "node_modules/requirejs": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.7.tgz", "integrity": "sha512-DouTG8T1WanGok6Qjg2SXuCMzszOo0eHeH9hDZ5Y4x8Je+9JB38HdTLT4/VA8OaUhBa0JPVHJ0pyBkM1z+pDsw==", "dev": true, + "license": "MIT", "bin": { "r_js": "bin/r.js", "r.js": "bin/r.js" @@ -17811,9 +14256,8 @@ }, "node_modules/requirejs-config-file": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/requirejs-config-file/-/requirejs-config-file-4.0.0.tgz", - "integrity": "sha512-jnIre8cbWOyvr8a5F2KuqBnY+SDA4NXr/hzEZJG79Mxm2WiFQz2dzhC8ibtPJS7zkmBEl1mxSwp5HhC1W4qpxw==", "dev": true, + "license": "MIT", "dependencies": { "esprima": "^4.0.0", "stringify-object": "^3.2.1" @@ -17830,12 +14274,11 @@ "license": "MIT" }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.8", "dev": true, + "license": "MIT", "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -17848,9 +14291,8 @@ }, "node_modules/resolve-cwd": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, + "license": "MIT", "dependencies": { "resolve-from": "^5.0.0" }, @@ -17859,28 +14301,25 @@ } }, "node_modules/resolve-dependency-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-dependency-path/-/resolve-dependency-path-2.0.0.tgz", - "integrity": "sha512-DIgu+0Dv+6v2XwRaNWnumKu7GPufBBOr5I1gRPJHkvghrfCGOooJODFvgFimX/KRxk9j0whD2MnKHzM1jYvk9w==", + "version": "3.0.2", "dev": true, + "license": "MIT", "engines": { - "node": ">=6.0.0" + "node": ">=14" } }, "node_modules/resolve-from": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/restore-cursor": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, + "license": "MIT", "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -17891,16 +14330,14 @@ }, "node_modules/retry": { "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/reusify": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -17908,25 +14345,81 @@ }, "node_modules/rfdc": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + "license": "MIT" }, "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, + "version": "5.0.7", + "license": "ISC", "dependencies": { - "glob": "^7.1.3" + "glob": "^10.3.7" }, "bin": { - "rimraf": "bin.js" + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "10.3.15", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.11.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "9.0.4", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minipass": { + "version": "7.1.1", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/run-async": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" } }, "node_modules/run-parallel": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "funding": [ { "type": "github", @@ -17941,56 +14434,54 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } }, "node_modules/rxjs": { "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/rxjs/node_modules/tslib": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true + "dev": true, + "license": "0BSD" }, "node_modules/safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "license": "MIT" }, "node_modules/sass-lookup": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/sass-lookup/-/sass-lookup-3.0.0.tgz", - "integrity": "sha512-TTsus8CfFRn1N44bvdEai1no6PqdmDiQUiqW5DlpmtT+tYnIt1tXtDIph5KA1efC+LmioJXSnCtUVpcK9gaKIg==", + "version": "5.0.1", "dev": true, + "license": "MIT", "dependencies": { - "commander": "^2.16.0" + "commander": "^10.0.1" }, "bin": { "sass-lookup": "bin/cli.js" }, "engines": { - "node": ">=6.0.0" + "node": ">=14" } }, "node_modules/sass-lookup/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "version": "10.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } }, "node_modules/scroll-into-view-if-needed": { "version": "2.2.29", @@ -18010,17 +14501,12 @@ }, "node_modules/select": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", - "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.2", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -18028,27 +14514,10 @@ "node": ">=10" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/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/serialize-error": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.13.1" }, @@ -18061,9 +14530,8 @@ }, "node_modules/serialize-error/node_modules/type-fest": { "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -18073,21 +14541,22 @@ }, "node_modules/set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + "dev": true, + "license": "ISC" }, "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, + "license": "MIT", "dependencies": { - "define-data-property": "^1.1.2", + "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -18095,9 +14564,8 @@ }, "node_modules/shallow-clone": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, + "license": "MIT", "dependencies": { "kind-of": "^6.0.2" }, @@ -18105,19 +14573,9 @@ "node": ">=8" } }, - "node_modules/shallow-clone/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.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==", + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -18127,39 +14585,25 @@ }, "node_modules/shebang-command/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==", + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/shebang-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-2.0.0.tgz", - "integrity": "sha1-9QC/aFG2E1YjYWfeLMMZsP1/BoE=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/shell-quote": { "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/shiki": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.11.1.tgz", - "integrity": "sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==", + "version": "1.10.0", "dev": true, + "license": "MIT", "dependencies": { - "jsonc-parser": "^3.0.0", - "vscode-oniguruma": "^1.6.1", - "vscode-textmate": "^6.0.0" + "@shikijs/core": "1.10.0" } }, "node_modules/side-channel": { @@ -18183,14 +14627,12 @@ }, "node_modules/signal-exit": { "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/sigstore": { "version": "2.2.2", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.2.2.tgz", - "integrity": "sha512-2A3WvXkQurhuMgORgT60r6pOWiCOO5LlEqY2ADxGBDGVYLSo5HN0uLtb68YpVpuL/Vi8mLTe7+0Dx2Fq8lLqEg==", + "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^2.2.0", "@sigstore/core": "^1.0.0", @@ -18205,24 +14647,21 @@ }, "node_modules/sisteransi": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/slash": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/slice-ansi": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" @@ -18236,9 +14675,8 @@ }, "node_modules/slice-ansi/node_modules/ansi-styles": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -18248,9 +14686,8 @@ }, "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -18260,8 +14697,7 @@ }, "node_modules/smart-buffer": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -18269,8 +14705,7 @@ }, "node_modules/socks": { "version": "2.7.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.3.tgz", - "integrity": "sha512-vfuYK48HXCTFD03G/1/zkIls3Ebr2YNa4qU9gHDZdblHLiqhJrJGkY3+0Nx0JpN9qBhJbVObc1CNciT1bIZJxw==", + "license": "MIT", "dependencies": { "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" @@ -18282,9 +14717,8 @@ }, "node_modules/socks-proxy-agent": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", @@ -18294,11 +14728,24 @@ "node": ">= 10" } }, + "node_modules/sort-keys": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-obj": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -18308,30 +14755,27 @@ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-support": { "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "node_modules/spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", + "version": "0.0.2", "dev": true }, "node_modules/spdx-correct": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "license": "Apache-2.0", "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -18339,13 +14783,11 @@ }, "node_modules/spdx-exceptions": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -18353,24 +14795,20 @@ }, "node_modules/spdx-license-ids": { "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==" + "license": "CC0-1.0" }, "node_modules/split.js": { "version": "1.6.5", - "resolved": "https://registry.npmjs.org/split.js/-/split.js-1.6.5.tgz", - "integrity": "sha512-mPTnGCiS/RiuTNsVhCm9De9cCAUsrNFFviRbADdKiiV+Kk8HKp/0fWu7Kr8pi3/yBmsqLFHuXGT9UUZ+CNLwFw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/sprintf-js": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/ssh2": { "version": "1.15.0", - "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.15.0.tgz", - "integrity": "sha512-C0PHgX4h6lBxYx7hcXwu3QWdh4tg6tZZsTfXcdvc5caW/EMxaB4H9dWsl7qk+F7LAW762hp8VbXOX7x4xUYvEw==", "hasInstallScript": true, "dependencies": { "asn1": "^0.2.6", @@ -18386,9 +14824,8 @@ }, "node_modules/ssri": { "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", "dev": true, + "license": "ISC", "dependencies": { "minipass": "^3.1.1" }, @@ -18398,17 +14835,15 @@ }, "node_modules/stack-trace": { "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "license": "MIT", "engines": { "node": "*" } }, "node_modules/stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "version": "2.0.6", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^2.0.0" }, @@ -18418,92 +14853,78 @@ }, "node_modules/stack-utils/node_modules/escape-string-regexp": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", + "node_modules/stream-to-array": { + "version": "2.3.0", "dev": true, + "license": "MIT", "dependencies": { - "duplexer": "~0.1.1" + "any-promise": "^1.1.0" } }, "node_modules/stream-to-string": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/stream-to-string/-/stream-to-string-1.2.1.tgz", - "integrity": "sha512-WsvTDNF8UYs369Yko3pcdTducQtYpzEZeOV7cTuReyFvOoA9S/DLJ6sYK+xPafSPHhUMpaxiljKYnT6JSFztIA==", "dev": true, + "license": "MIT", "dependencies": { "promise-polyfill": "^1.1.6" } }, "node_modules/streamroller": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.8.tgz", - "integrity": "sha512-VI+ni3czbFZrd1MrlybxykWZ8sMDCMtTU7YJyhgb9M5X6d1DDxLdJr+gSnmRpXPMnIWxWKMaAE8K0WumBp3lDg==", + "version": "3.1.5", + "license": "MIT", "dependencies": { - "date-format": "^4.0.9", + "date-format": "^4.0.14", "debug": "^4.3.4", - "fs-extra": "^10.1.0" + "fs-extra": "^8.1.0" }, "engines": { "node": ">=8.0" } }, "node_modules/streamroller/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "version": "8.1.0", + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, "engines": { - "node": ">=12" + "node": ">=6 <7 || >=8" } }, "node_modules/streamroller/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "version": "4.0.0", "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, + "node_modules/streamroller/node_modules/universalify": { + "version": "0.1.2", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } }, - "node_modules/string-argv": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.1.2.tgz", - "integrity": "sha512-mBqPGEOMNJKXRo7z0keX0wlAhbBAjilUdPW13nN0PecVryZxdHIeM7TqbsSUA7VYuS00HGC6mojP7DlQzfa9ZA==", - "dev": true, - "engines": { - "node": ">=0.6.19" - } - }, "node_modules/string-length": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, + "license": "MIT", "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" @@ -18514,8 +14935,7 @@ }, "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==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -18528,8 +14948,7 @@ "node_modules/string-width-cjs": { "name": "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==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -18541,9 +14960,8 @@ }, "node_modules/stringify-object": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "get-own-enumerable-property-symbols": "^3.0.0", "is-obj": "^1.0.1", @@ -18555,8 +14973,7 @@ }, "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==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -18567,8 +14984,7 @@ "node_modules/strip-ansi-cjs": { "name": "strip-ansi", "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -18578,43 +14994,38 @@ }, "node_modules/strip-ansi-cjs/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==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/strip-ansi/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==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/strip-bom": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/strip-final-newline": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "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, + "license": "MIT", "engines": { "node": ">=8" }, @@ -18624,9 +15035,8 @@ }, "node_modules/strong-log-transformer": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", - "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "duplexer": "^0.1.1", "minimist": "^1.2.0", @@ -18640,32 +15050,31 @@ } }, "node_modules/stylus-lookup": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/stylus-lookup/-/stylus-lookup-3.0.2.tgz", - "integrity": "sha512-oEQGHSjg/AMaWlKe7gqsnYzan8DLcGIHe0dUaFkucZZ14z4zjENRlQMCHT4FNsiWnJf17YN9OvrCfCoi7VvOyg==", + "version": "5.0.1", "dev": true, + "license": "MIT", "dependencies": { - "commander": "^2.8.1", - "debug": "^4.1.0" + "commander": "^10.0.1" }, "bin": { "stylus-lookup": "bin/cli.js" }, "engines": { - "node": ">=6.0.0" + "node": ">=14" } }, "node_modules/stylus-lookup/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "version": "10.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } }, "node_modules/supertap": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/supertap/-/supertap-3.0.1.tgz", - "integrity": "sha512-u1ZpIBCawJnO+0QePsEiOknOfCRq0yERxiAchT0i4li0WHNUJbf0evXXSXOcCAR4M8iMDoajXYmstm/qO81Isw==", "dev": true, + "license": "MIT", "dependencies": { "indent-string": "^5.0.0", "js-yaml": "^3.14.1", @@ -18676,32 +15085,18 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/supertap/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, "node_modules/supertap/node_modules/argparse": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } }, "node_modules/supertap/node_modules/indent-string": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -18711,9 +15106,8 @@ }, "node_modules/supertap/node_modules/js-yaml": { "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -18724,9 +15118,8 @@ }, "node_modules/supertap/node_modules/strip-ansi": { "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -18739,8 +15132,7 @@ }, "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==", + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -18750,9 +15142,8 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -18761,34 +15152,31 @@ } }, "node_modules/symlink-dir": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/symlink-dir/-/symlink-dir-5.1.1.tgz", - "integrity": "sha512-kmVV2SfdoDksjJxStJ5N9u1ZZ5tQndCeUEG8St0tHI9BZe/ehZYbKB6eXPjo+AvFG1uRsDymUSGG0OLv2Ox8aQ==", + "version": "6.0.0", "dev": true, + "license": "MIT", "dependencies": { "better-path-resolve": "^1.0.0", - "rename-overwrite": "^4.0.3" + "rename-overwrite": "^5.0.0" }, "bin": { "symlink-dir": "dist/cli.js" }, "engines": { - "node": ">=12.10" + "node": ">=18.12" } }, "node_modules/tapable": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/tar": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -18803,39 +15191,34 @@ }, "node_modules/tar/node_modules/chownr": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/tar/node_modules/minipass": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", "engines": { "node": ">=8" } }, "node_modules/tar/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, - "node_modules/temp": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.4.0.tgz", - "integrity": "sha1-ZxrWPVe+D+nXKUZks/xABjZnimA=", + "node_modules/temp-dir": { + "version": "3.0.0", "dev": true, - "engines": [ - "node >=0.4.0" - ] + "license": "MIT", + "engines": { + "node": ">=14.16" + } }, "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, + "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -18847,45 +15230,31 @@ }, "node_modules/text-table": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/through": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "node_modules/time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", "dev": true, - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, "node_modules/time-zone": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", - "integrity": "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/tiny-emitter": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", - "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/tmp": { "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, + "license": "MIT", "dependencies": { "os-tmpdir": "~1.0.2" }, @@ -18895,23 +15264,20 @@ }, "node_modules/tmpl": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/to-regex-range": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -18919,29 +15285,31 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "dev": true, + "license": "MIT" + }, "node_modules/tree-kill": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true, + "license": "MIT", "bin": { "tree-kill": "cli.js" } }, "node_modules/treeverse": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/treeverse/-/treeverse-2.0.0.tgz", - "integrity": "sha512-N5gJCkLu1aXccpOTtqV6ddSEi6ZmGkh3hjmbu1IjcavJK4qyOVQmi0myQKM7z5jVGmD68SJoliaVrMmVObhj6A==", "dev": true, + "license": "ISC", "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/ts-api-utils": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -18949,11 +15317,22 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-graphviz": { + "version": "1.8.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ts-graphviz" + } + }, "node_modules/ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "version": "29.1.5", "dev": true, + "license": "MIT", "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", @@ -18968,10 +15347,11 @@ "ts-jest": "cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", "@jest/types": "^29.0.0", "babel-jest": "^29.0.0", "jest": "^29.0.0", @@ -18981,6 +15361,9 @@ "@babel/core": { "optional": true }, + "@jest/transform": { + "optional": true + }, "@jest/types": { "optional": true }, @@ -18994,9 +15377,8 @@ }, "node_modules/ts-jest/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -19009,20 +15391,10 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/ts-jest/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/ts-node": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", - "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", "dev": true, + "license": "MIT", "dependencies": { "arrify": "^1.0.0", "buffer-from": "^1.1.0", @@ -19042,18 +15414,16 @@ }, "node_modules/ts-node/node_modules/diff": { "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/ts-node/node_modules/mkdirp": { "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.6" }, @@ -19061,39 +15431,36 @@ "mkdirp": "bin/cmd.js" } }, - "node_modules/tsc-watch": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-5.0.3.tgz", - "integrity": "sha512-Hz2UawwELMSLOf0xHvAFc7anLeMw62cMVXr1flYmhRuOhOyOljwmb1l/O60ZwRyy1k7N1iC1mrn1QYM2zITfuw==", + "node_modules/tsconfig-paths": { + "version": "4.2.0", "dev": true, + "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "node-cleanup": "^2.1.2", - "ps-tree": "^1.2.0", - "string-argv": "^0.1.1", - "strip-ansi": "^6.0.0" - }, - "bin": { - "tsc-watch": "index.js" + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" }, "engines": { - "node": ">=8.17.0" - }, - "peerDependencies": { - "typescript": "*" + "node": ">=6" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" } }, "node_modules/tslib": { "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "dev": true, + "license": "0BSD" }, "node_modules/tsutils": { "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^1.8.1" }, @@ -19106,8 +15473,7 @@ }, "node_modules/tuf-js": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.0.tgz", - "integrity": "sha512-ZSDngmP1z6zw+FIkIBjvOp/II/mIub/O7Pp12j1WNsiCpg5R5wAc//i555bBQsE44O94btLt0xM/Zr2LQjwdCg==", + "license": "MIT", "dependencies": { "@tufjs/models": "2.0.0", "debug": "^4.3.4", @@ -19119,8 +15485,7 @@ }, "node_modules/tuf-js/node_modules/@npmcli/fs": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "license": "ISC", "dependencies": { "semver": "^7.3.5" }, @@ -19130,16 +15495,14 @@ }, "node_modules/tuf-js/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==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/tuf-js/node_modules/cacache": { "version": "18.0.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", - "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", + "license": "ISC", "dependencies": { "@npmcli/fs": "^3.1.0", "fs-minipass": "^3.0.0", @@ -19160,8 +15523,7 @@ }, "node_modules/tuf-js/node_modules/fs-minipass": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -19171,8 +15533,7 @@ }, "node_modules/tuf-js/node_modules/glob": { "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^2.3.5", @@ -19192,8 +15553,7 @@ }, "node_modules/tuf-js/node_modules/make-fetch-happen": { "version": "13.0.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", - "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", + "license": "ISC", "dependencies": { "@npmcli/agent": "^2.0.0", "cacache": "^18.0.0", @@ -19213,8 +15573,7 @@ }, "node_modules/tuf-js/node_modules/minimatch": { "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -19227,16 +15586,14 @@ }, "node_modules/tuf-js/node_modules/minipass": { "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/tuf-js/node_modules/minipass-collect": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -19246,8 +15603,7 @@ }, "node_modules/tuf-js/node_modules/minipass-fetch": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "license": "MIT", "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", @@ -19262,8 +15618,7 @@ }, "node_modules/tuf-js/node_modules/ssri": { "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, @@ -19273,8 +15628,7 @@ }, "node_modules/tuf-js/node_modules/unique-filename": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "license": "ISC", "dependencies": { "unique-slug": "^4.0.0" }, @@ -19284,8 +15638,7 @@ }, "node_modules/tuf-js/node_modules/unique-slug": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, @@ -19295,14 +15648,12 @@ }, "node_modules/tweetnacl": { "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + "license": "Unlicense" }, "node_modules/type-check": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -19312,18 +15663,16 @@ }, "node_modules/type-detect": { "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/type-fest": { "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -19333,78 +15682,75 @@ }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, + "license": "MIT", "dependencies": { "is-typedarray": "^1.0.0" } }, "node_modules/typedoc": { - "version": "0.23.17", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.17.tgz", - "integrity": "sha512-3rtNubo1dK0pvs6ixpMAq4pESULd5/JNUqJbdyZoeilI14reb1RNVomN4fMgIadd0RMX1aenYjJSSMBOJ+/+0Q==", + "version": "0.26.3", "dev": true, + "license": "Apache-2.0", "dependencies": { "lunr": "^2.3.9", - "marked": "^4.0.19", - "minimatch": "^5.1.0", - "shiki": "^0.11.1" + "markdown-it": "^14.1.0", + "minimatch": "^9.0.5", + "shiki": "^1.9.1", + "yaml": "^2.4.5" }, "bin": { "typedoc": "bin/typedoc" }, "engines": { - "node": ">= 14.14" + "node": ">= 18" }, "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x" + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x" } }, "node_modules/typedoc/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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/typedoc/node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "9.0.5", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "version": "5.5.3", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/uc.micro": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==" + "license": "MIT" }, "node_modules/uglify-js": { "version": "3.17.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.3.tgz", - "integrity": "sha512-JmMFDME3iufZnBpyKL+uS78LRiC+mK55zWfM5f/pWBJfpOttXAqYfdDGRukYhJuyRinvPVAtUhvy7rlDybNtFg==", "dev": true, + "license": "BSD-2-Clause", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -19415,14 +15761,17 @@ }, "node_modules/underscore": { "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "5.26.5", + "dev": true, + "license": "MIT" }, "node_modules/unicorn-magic": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -19442,49 +15791,38 @@ "node": ">= 0.8.0" } }, - "node_modules/uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, "node_modules/unique-filename": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", "dev": true, + "license": "ISC", "dependencies": { "unique-slug": "^2.0.0" } }, "node_modules/unique-slug": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" } }, "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", - "dev": true + "version": "7.0.2", + "dev": true, + "license": "ISC" }, "node_modules/universalify": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "license": "MIT", "engines": { "node": ">= 10.0.0" } }, "node_modules/upath": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", - "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", "dev": true, + "license": "MIT", "engines": { "node": ">=4", "yarn": "*" @@ -19492,8 +15830,6 @@ }, "node_modules/update-browserslist-db": { "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "dev": true, "funding": [ { @@ -19509,6 +15845,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -19522,9 +15859,8 @@ }, "node_modules/uri-js": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -19538,82 +15874,69 @@ }, "node_modules/url-search-params-polyfill": { "version": "8.2.5", - "resolved": "https://registry.npmjs.org/url-search-params-polyfill/-/url-search-params-polyfill-8.2.5.tgz", - "integrity": "sha512-FOEojW4XReTmtZOB7xqSHmJZhrNTmClhBriwLTmle4iA7bwuCo6ldSfbtsFSb8bTf3E0a3XpfonAdaur9vqq8A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/uuid": { "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true, + "license": "MIT", "optional": true, "peer": true }, "node_modules/validate-npm-package-license": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "license": "Apache-2.0", "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, - "node_modules/vscode-oniguruma": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", - "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==", - "dev": true - }, - "node_modules/vscode-textmate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-6.0.0.tgz", - "integrity": "sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==", - "dev": true + "node_modules/validate-npm-package-name": { + "version": "5.0.1", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } }, "node_modules/walk-up-path": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-1.0.0.tgz", - "integrity": "sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/walkdir": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.4.1.tgz", - "integrity": "sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/walker": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "makeerror": "1.0.12" } }, "node_modules/wcwidth": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", "dev": true, + "license": "MIT", "dependencies": { "defaults": "^1.0.3" } @@ -19624,18 +15947,21 @@ }, "node_modules/web-streams-polyfill": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "dev": true, + "license": "BSD-2-Clause" + }, "node_modules/well-known-symbols": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", - "integrity": "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==", "dev": true, + "license": "ISC", "engines": { "node": ">=6" } @@ -19666,10 +15992,18 @@ "node": ">=0.10.0" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -19682,45 +16016,40 @@ }, "node_modules/which-module": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + "dev": true, + "license": "ISC" }, "node_modules/wide-align": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } }, "node_modules/wontache": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/wontache/-/wontache-0.1.0.tgz", - "integrity": "sha512-UH4ikvEVRtvqY3DoW9/NjctB11FDuHjkKPO1tjaUVIVnZevxNtvba7lhR7H5TfMBVCpF2jwxH1qlu0UQSQ/zCw==", + "license": "BSD-3-Clause", "dependencies": { "underscore": "^1.13.0-2" } }, "node_modules/word-wrap": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/wordwrap": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true + "dev": true, + "license": "MIT" }, "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==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -19736,8 +16065,7 @@ "node_modules/wrap-ansi-cjs": { "name": "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==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -19752,14 +16080,13 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "dev": true, + "license": "ISC" }, "node_modules/write-file-atomic": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" @@ -19768,156 +16095,158 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/write-json-file": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-indent": "^7.0.0", + "is-plain-obj": "^4.0.0", + "sort-keys": "^5.0.0", + "write-file-atomic": "^3.0.3" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/write-json-file/node_modules/write-file-atomic": { + "version": "3.0.3", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/write-package": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "deepmerge-ts": "^5.1.0", + "read-pkg": "^9.0.0", + "sort-keys": "^5.0.0", + "type-fest": "^4.6.0", + "write-json-file": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/write-package/node_modules/type-fest": { + "version": "4.20.1", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/xml": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/xmlbuilder": { "version": "15.0.0", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.0.0.tgz", - "integrity": "sha512-KLu/G0DoWhkncQ9eHSI6s0/w+T4TM7rQaLhtCaL6tORv8jFlJPlnGumsgTcGfYeS1qZ/IHqrvDG7zJZ4d7e+nw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.0" } }, "node_modules/xxhashjs": { "version": "0.2.2", - "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz", - "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==", "dev": true, + "license": "MIT", "dependencies": { "cuint": "^0.2.2" } }, "node_modules/y18n": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + "dev": true, + "license": "ISC" }, "node_modules/yallist": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, - "node_modules/yamljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", - "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", - "dependencies": { - "argparse": "^1.0.7", - "glob": "^7.0.5" - }, + "node_modules/yaml": { + "version": "2.4.5", + "dev": true, + "license": "ISC", "bin": { - "json2yaml": "bin/json2yaml", - "yaml2json": "bin/yaml2json" - } - }, - "node_modules/yamljs/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/yargs": { - "version": "15.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", - "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "yaml": "bin.mjs" }, "engines": { - "node": ">=8" + "node": ">= 14" } }, - "node_modules/yargs/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/yargs": { + "version": "17.7.2", + "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "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": ">=8" + "node": ">=12" } }, - "node_modules/yargs/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "license": "ISC", "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/yargs/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/yargs/node_modules/cliui": { + "version": "8.0.1", + "license": "ISC", "dependencies": { - "p-limit": "^2.2.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, + "node_modules/yargs/node_modules/y18n": { + "version": "5.0.8", + "license": "ISC", "engines": { - "node": ">=6" + "node": ">=10" } }, "node_modules/yn": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "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==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -19925,169 +16254,187 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "packages/cli": { "name": "@zowe/cli", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "hasInstallScript": true, "license": "EPL-2.0", "dependencies": { - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1", - "@zowe/provisioning-for-zowe-sdk": "7.29.2", - "@zowe/zos-console-for-zowe-sdk": "7.29.2", - "@zowe/zos-files-for-zowe-sdk": "7.29.2", - "@zowe/zos-jobs-for-zowe-sdk": "7.29.2", - "@zowe/zos-logs-for-zowe-sdk": "7.29.2", - "@zowe/zos-tso-for-zowe-sdk": "7.29.2", - "@zowe/zos-uss-for-zowe-sdk": "7.29.2", - "@zowe/zos-workflows-for-zowe-sdk": "7.29.2", - "@zowe/zosmf-for-zowe-sdk": "7.29.2", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528", + "@zowe/provisioning-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/zos-console-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/zos-jobs-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/zos-logs-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/zos-tso-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/zos-uss-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/zos-workflows-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/zosmf-for-zowe-sdk": "8.0.0-next.202409111528", "find-process": "1.4.7", - "get-stream": "6.0.1", "lodash": "4.17.21", - "minimatch": "5.0.1", + "minimatch": "9.0.5", "tar": "6.2.1" }, "bin": { - "bright": "lib/main.js", "zowe": "lib/main.js" }, "devDependencies": { - "@types/diff": "^5.0.2", - "@types/lodash": "^4.14.175", - "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "7.29.2", - "comment-json": "^4.1.1", + "@types/diff": "^5.0.9", + "@types/lodash": "^4.17.6", + "@types/tar": "^6.1.11", + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "comment-json": "^4.2.3", "strip-ansi": "^6.0.1", - "which": "^2.0.2" + "which": "^4.0.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.12.0" }, "optionalDependencies": { - "@zowe/secrets-for-zowe-sdk": "7.18.6" - } - }, - "packages/cli/node_modules/@zowe/secrets-for-zowe-sdk": { - "version": "7.18.6", - "resolved": "https://zowe.jfrog.io/zowe/api/npm/npm-local-release/@zowe/secrets-for-zowe-sdk/-/@zowe/secrets-for-zowe-sdk-7.18.6.tgz", - "integrity": "sha512-3ElVUd5VYWUxVjXRCeM/jmXh9u1rnWtxobQEpgEZ2iNt+PTt3QajIxUH9MxriELVCp7u39AeAG4lfxs3wnrGzA==", - "hasInstallScript": true, - "license": "EPL-2.0", - "optional": true, - "engines": { - "node": ">= 14" + "@zowe/secrets-for-zowe-sdk": "8.0.0-next.202409111528" } }, "packages/cli/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==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, - "packages/cli/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==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "packages/cli/node_modules/isexe": { + "version": "3.1.1", + "dev": true, + "license": "ISC", "engines": { - "node": ">=10" + "node": ">=16" + } + }, + "packages/cli/node_modules/minimatch": { + "version": "9.0.5", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/cli/node_modules/which": { + "version": "4.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" } }, "packages/core": { "name": "@zowe/core-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "license": "EPL-2.0", "dependencies": { - "comment-json": "4.1.1", - "string-width": "4.2.3" + "comment-json": "~4.2.3", + "string-width": "^4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/imperative": "5.27.1" + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" + }, + "engines": { + "node": ">=18.12.0" }, "peerDependencies": { - "@zowe/imperative": "^5.0.0" + "@zowe/imperative": "^8.0.0-next" } }, "packages/imperative": { "name": "@zowe/imperative", - "version": "5.27.1", + "version": "8.0.0-next.202409111528", "license": "EPL-2.0", "dependencies": { - "@types/yargs": "13.0.4", - "chalk": "2.4.2", - "cli-table3": "0.6.2", - "comment-json": "4.1.1", - "cross-spawn": "7.0.3", - "dataobject-parser": "1.2.25", - "deepmerge": "4.2.2", - "diff": "5.1.0", + "@types/yargs": "^17.0.32", + "chalk": "^4.1.2", + "cli-table3": "^0.6.3", + "comment-json": "~4.2.3", + "cross-spawn": "^7.0.3", + "dataobject-parser": "^1.2.25", + "deepmerge": "^4.3.1", + "diff": "^5.2.0", "diff2html": "3.4.20-usewontache.1.60e7a2e", - "fast-glob": "3.2.7", - "fastest-levenshtein": "1.0.12", - "find-up": "4.1.0", - "fs-extra": "9.1.0", + "fast-glob": "^3.3.2", + "fastest-levenshtein": "^1.0.16", + "find-up": "^5.0.0", + "fs-extra": "^11.0.0", "http-proxy-agent": "7.0.2", "https-proxy-agent": "7.0.4", - "jest-diff": "27.0.6", - "js-yaml": "4.1.0", - "jsonfile": "6.1.0", - "jsonschema": "1.4.1", - "lodash": "4.17.21", - "lodash-deep": "2.0.0", - "log4js": "6.4.6", - "markdown-it": "14.1.0", - "mustache": "4.2.0", - "npm-package-arg": "9.1.0", - "opener": "1.5.2", - "pacote": "17.0.6", - "prettyjson": "1.2.2", - "progress": "2.0.3", - "read": "1.0.7", - "readline-sync": "1.4.10", - "semver": "7.5.4", - "stack-trace": "0.0.10", - "strip-ansi": "6.0.1", - "which": "4.0.0", - "wrap-ansi": "7.0.0", - "yamljs": "0.3.0", - "yargs": "15.3.1" + "jest-diff": "^29.0.0", + "js-yaml": "^4.1.0", + "jsonfile": "^6.0.0", + "jsonschema": "^1.4.1", + "lodash": "^4.17.21", + "lodash-deep": "^2.0.0", + "log4js": "^6.9.1", + "markdown-it": "^14.1.0", + "mustache": "^4.2.0", + "npm-package-arg": "^11.0.1", + "opener": "^1.5.2", + "pacote": "^18.0.6", + "prettyjson": "^1.2.5", + "progress": "^2.0.3", + "read": "^3.0.1", + "semver": "^7.5.2", + "stack-trace": "^0.0.10", + "strip-ansi": "^6.0.1", + "which": "^4.0.0", + "wrap-ansi": "^7.0.0", + "yargs": "^17.7.2" }, "devDependencies": { - "@types/cross-spawn": "^6.0.2", - "@types/diff": "^5.0.2", - "@types/find-up": "^2.1.1", - "@types/fs-extra": "^9.0.13", - "@types/glob": "^7.1.1", - "@types/jsonfile": "^6.1.0", - "@types/lodash": "^4.14.165", - "@types/lodash-deep": "^2.0.0", - "@types/mustache": "^0.8.32", - "@types/npm-package-arg": "^6.1.0", - "@types/pacote": "^11.1.0", - "@types/progress": "^2.0.3", - "@types/readline-sync": "^1.4.3", - "@types/rimraf": "^3.0.2", - "@types/stack-trace": "^0.0.29", - "@zowe/secrets-for-zowe-sdk": "^7.18.0", - "concurrently": "^7.5.0", - "cowsay": "^1.2.1", - "deep-diff": "^0.3.8", + "@types/cross-spawn": "^6.0.6", + "@types/diff": "^5.0.9", + "@types/fs-extra": "^11.0.4", + "@types/glob": "^8.1.0", + "@types/jsonfile": "^6.1.4", + "@types/lodash": "^4.17.6", + "@types/lodash-deep": "^2.0.4", + "@types/mustache": "^4.2.5", + "@types/npm-package-arg": "^6.1.4", + "@types/pacote": "^11.1.8", + "@types/progress": "^2.0.7", + "@types/stack-trace": "^0.0.33", + "@zowe/secrets-for-zowe-sdk": "8.0.0-next.202409111528", + "concurrently": "^8.0.0", + "cowsay": "^1.6.0", + "deep-diff": "^1.0.0", "get-function-arguments": "^1.0.0", "http-server": "^14.1.1", "stream-to-string": "^1.2.0", - "tsc-watch": "^5.0.3", - "uuid": "^3.3.2", + "uuid": "^10.0.0", "web-help": "file:web-help", - "yargs-parser": "^18.1.2" + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.12.0" } }, "packages/imperative/node_modules/agent-base": { @@ -20101,55 +16448,16 @@ "node": ">= 14" } }, - "packages/imperative/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "packages/imperative/node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dependencies": { - "semver": "^7.0.0" - } - }, - "packages/imperative/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, + "packages/imperative/node_modules/diff": { + "version": "5.2.0", + "license": "BSD-3-Clause", "engines": { - "node": ">=4" - } - }, - "packages/imperative/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": ">=0.3.1" } }, - "packages/imperative/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==" - }, "packages/imperative/node_modules/diff2html": { "version": "3.4.20-usewontache.1.60e7a2e", - "resolved": "https://registry.npmjs.org/diff2html/-/diff2html-3.4.20-usewontache.1.60e7a2e.tgz", - "integrity": "sha512-0ge1jQpRv9Eg6USdIgnDIzAnuhhlgFPmhglCUBNhSVU772biWWbSu/palu0uK+PbgidjkjkajztZGVAZnD56pw==", + "license": "MIT", "dependencies": { "diff": "5.1.0", "wontache": "0.1.0" @@ -20161,54 +16469,21 @@ "highlight.js": "11.6.0" } }, - "packages/imperative/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "packages/imperative/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "packages/imperative/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==", + "packages/imperative/node_modules/diff2html/node_modules/diff": { + "version": "5.1.0", + "license": "BSD-3-Clause", "engines": { - "node": ">=4" + "node": ">=0.3.1" } }, "packages/imperative/node_modules/highlight.js": { "version": "11.6.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.6.0.tgz", - "integrity": "sha512-ig1eqDzJaB0pqEvlPVIpSSyMaO92bH1N2rJpLMN/nX396wTpDA4Eq0uK+7I/2XG17pFaaKE0kjV/XPeGt7Evjw==", + "license": "BSD-3-Clause", "optional": true, "engines": { "node": ">=12.0.0" } }, - "packages/imperative/node_modules/hosted-git-info": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", - "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", - "dependencies": { - "lru-cache": "^7.5.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "packages/imperative/node_modules/http-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", @@ -20235,118 +16510,26 @@ }, "packages/imperative/node_modules/isexe": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "license": "ISC", "engines": { "node": ">=16" } }, - "packages/imperative/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "packages/imperative/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "packages/imperative/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "engines": { - "node": ">=12" - } - }, - "packages/imperative/node_modules/npm-package-arg": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.0.tgz", - "integrity": "sha512-4J0GL+u2Nh6OnhvUKXRr2ZMG4lR8qtLp+kv7UiV00Y+nGiSxtttCyIRHCt5L5BNkXQld/RceYItau3MDOoGiBw==", - "dependencies": { - "hosted-git-info": "^5.0.0", - "proc-log": "^2.0.1", - "semver": "^7.3.5", - "validate-npm-package-name": "^4.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "packages/imperative/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "packages/imperative/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "packages/imperative/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "packages/imperative/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "version": "10.0.0", "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "uuid": "bin/uuid" - } - }, - "packages/imperative/node_modules/validate-npm-package-name": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz", - "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", - "dependencies": { - "builtins": "^5.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "uuid": "dist/bin/uuid" } }, "packages/imperative/node_modules/which": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "license": "ISC", "dependencies": { "isexe": "^3.1.1" }, @@ -20357,19 +16540,6 @@ "node": "^16.13.0 || >=18.0.0" } }, - "packages/imperative/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, "packages/imperative/web-help": { "dev": true, "license": "ISC", @@ -20393,15306 +16563,208 @@ }, "packages/provisioning": { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "license": "EPL-2.0", "dependencies": { - "js-yaml": "4.1.0" + "js-yaml": "^4.1.0" }, "devDependencies": { - "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" + "@types/js-yaml": "^4.0.9", + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" + }, + "engines": { + "node": ">=18.12.0" }, "peerDependencies": { - "@zowe/core-for-zowe-sdk": "^7.0.0", - "@zowe/imperative": "^5.0.0" + "@zowe/core-for-zowe-sdk": "^8.0.0-next", + "@zowe/imperative": "^8.0.0-next" } }, "packages/secrets": { "name": "@zowe/secrets-for-zowe-sdk", - "version": "7.28.3", + "version": "8.0.0-next.202409111528", "hasInstallScript": true, "license": "EPL-2.0", "devDependencies": { - "@napi-rs/cli": "^2.16.2", - "ava": "^4.3.3" + "@napi-rs/cli": "^2.18.4", + "ava": "^6.0.0" }, "engines": { - "node": ">= 14" + "node": ">=14" } }, "packages/workflows": { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.29.2" + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202409111528" }, "devDependencies": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" + }, + "engines": { + "node": ">=18.12.0" }, "peerDependencies": { - "@zowe/core-for-zowe-sdk": "^7.0.0", - "@zowe/imperative": "^5.0.0" + "@zowe/core-for-zowe-sdk": "^8.0.0-next", + "@zowe/imperative": "^8.0.0-next" } }, "packages/zosconsole": { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" + }, + "engines": { + "node": ">=18.12.0" }, "peerDependencies": { - "@zowe/core-for-zowe-sdk": "^7.0.0", - "@zowe/imperative": "^5.0.0" + "@zowe/core-for-zowe-sdk": "^8.0.0-next", + "@zowe/imperative": "^8.0.0-next" } }, "packages/zosfiles": { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "license": "EPL-2.0", "dependencies": { - "minimatch": "5.0.1" + "minimatch": "^9.0.5" }, "devDependencies": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1", - "@zowe/zos-uss-for-zowe-sdk": "7.29.2" + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528", + "@zowe/zos-uss-for-zowe-sdk": "8.0.0-next.202409111528" + }, + "engines": { + "node": ">=18.12.0" }, "peerDependencies": { - "@zowe/core-for-zowe-sdk": "^7.0.0", - "@zowe/imperative": "^5.0.0" + "@zowe/core-for-zowe-sdk": "^8.0.0-next", + "@zowe/imperative": "^8.0.0-next" } }, "packages/zosfiles/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==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "packages/zosfiles/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==", + "version": "9.0.5", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "packages/zosjobs": { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "license": "EPL-2.0", "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.29.2" + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202409111528" }, "devDependencies": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" + }, + "engines": { + "node": ">=18.12.0" }, "peerDependencies": { - "@zowe/core-for-zowe-sdk": "^7.0.0", - "@zowe/imperative": "^5.0.0" + "@zowe/core-for-zowe-sdk": "^8.0.0-next", + "@zowe/imperative": "^8.0.0-next" } }, "packages/zoslogs": { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" + }, + "engines": { + "node": ">=18.12.0" }, "peerDependencies": { - "@zowe/core-for-zowe-sdk": "^7.0.0", - "@zowe/imperative": "^5.0.0" + "@zowe/core-for-zowe-sdk": "^8.0.0-next", + "@zowe/imperative": "^8.0.0-next" } }, "packages/zosmf": { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "license": "EPL-2.0", "devDependencies": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" + }, + "engines": { + "node": ">=18.12.0" }, "peerDependencies": { - "@zowe/core-for-zowe-sdk": "^7.0.0", - "@zowe/imperative": "^5.0.0" + "@zowe/core-for-zowe-sdk": "^8.0.0-next", + "@zowe/imperative": "^8.0.0-next" } }, "packages/zostso": { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "license": "EPL-2.0", "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "7.29.2" + "@zowe/zosmf-for-zowe-sdk": "8.0.0-next.202409111528" }, "devDependencies": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" + }, + "engines": { + "node": ">=18.12.0" }, "peerDependencies": { - "@zowe/core-for-zowe-sdk": "^7.0.0", - "@zowe/imperative": "^5.0.0" + "@zowe/core-for-zowe-sdk": "^8.0.0-next", + "@zowe/imperative": "^8.0.0-next" } }, "packages/zosuss": { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "license": "EPL-2.0", "dependencies": { - "ssh2": "1.15.0" + "ssh2": "^1.15.0" }, "devDependencies": { - "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "7.29.2", - "@zowe/imperative": "5.27.1" + "@types/ssh2": "^1.11.19", + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" }, - "peerDependencies": { - "@zowe/imperative": "^5.2.0" - } - } - }, - "dependencies": { - "@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", - "dev": true, - "requires": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "engines": { + "node": ">=18.12.0" }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "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==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "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 - }, - "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, - "requires": { - "has-flag": "^3.0.0" - } - } + "peerDependencies": { + "@zowe/imperative": "^8.0.0-next" } - }, - "@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", - "dev": true - }, - "@babel/core": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.0.tgz", - "integrity": "sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.0", - "@babel/parser": "^7.24.0", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.0", - "@babel/types": "^7.24.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "dependencies": { - "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 - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", - "dev": true, - "requires": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "dependencies": { - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true - }, - "@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "requires": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", - "dev": true, - "requires": { - "@babel/types": "^7.22.15" - } - }, - "@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", - "dev": true - }, - "@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", - "dev": true - }, - "@babel/helpers": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.0.tgz", - "integrity": "sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA==", - "dev": true, - "requires": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.0", - "@babel/types": "^7.24.0" - } - }, - "@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "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==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "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 - }, - "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, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz", - "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==", - "dev": true - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", - "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.22.5" - } - }, - "@babel/runtime": { - "version": "7.23.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.1.tgz", - "integrity": "sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.14.0" - } - }, - "@babel/template": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", - "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" - } - }, - "@babel/traverse": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.0.tgz", - "integrity": "sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - } - }, - "@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 - }, - "@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "optional": true - }, - "@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "dependencies": { - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - } - } - }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - } - } - }, - "@eslint/eslintrc": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", - "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - } - }, - "@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true - }, - "@humanwhocodes/config-array": { - "version": "0.10.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", - "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "requires": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - } - } - } - }, - "@isaacs/string-locale-compare": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz", - "integrity": "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==", - "dev": true - }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - } - } - }, - "@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 - }, - "@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "dependencies": { - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } - } - }, - "@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "dev": true, - "requires": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "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 - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "optional": true, - "peer": true - }, - "jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - } - }, - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - }, - "jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - } - }, - "jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "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, - "requires": { - "has-flag": "^4.0.0" - } - }, - "ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - } - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "optional": true, - "peer": true - } - } - }, - "@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, - "requires": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - } - }, - "@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, - "requires": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - } - }, - "@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, - "requires": { - "jest-get-type": "^29.6.3" - }, - "dependencies": { - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - } - } - }, - "@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "dependencies": { - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } - } - }, - "@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - } - }, - "@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "dependencies": { - "@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - } - }, - "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 - }, - "istanbul-lib-instrument": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", - "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - } - }, - "jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "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, - "requires": { - "has-flag": "^4.0.0" - } - }, - "v8-to-istanbul": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", - "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - } - } - } - }, - "@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "dependencies": { - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - } - } - }, - "@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "dev": true, - "requires": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "dev": true, - "requires": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "dependencies": { - "jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "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, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "@types/yargs": { - "version": "17.0.13", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", - "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - } - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "@kurkle/color": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", - "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==", - "dev": true - }, - "@lerna-lite/changed": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/changed/-/changed-3.3.1.tgz", - "integrity": "sha512-wOpO3ob1gUlkxcle5NnnngVmgpK355q5wwRdRp8pIOf09FL+C1YSN1jiWWfRP+PaDsMNi6cNg8bgn9GkyhHSIg==", - "dev": true, - "requires": { - "@lerna-lite/cli": "3.3.1", - "@lerna-lite/core": "3.3.1", - "@lerna-lite/list": "3.3.1", - "@lerna-lite/listable": "3.3.1" - } - }, - "@lerna-lite/cli": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/cli/-/cli-3.3.1.tgz", - "integrity": "sha512-tniFllcJtrR6SinS1AnDMzviZmnR1fInyIX1HZCIaDiiSz1O3FAM+QmrrFfSHl5HRaPpVGEPMP9KexTKZE+Csw==", - "dev": true, - "requires": { - "@lerna-lite/core": "3.3.1", - "@lerna-lite/init": "3.3.1", - "dedent": "^1.5.1", - "dotenv": "^16.4.5", - "import-local": "^3.1.0", - "load-json-file": "^7.0.1", - "npmlog": "^7.0.1", - "yargs": "^17.7.2" - }, - "dependencies": { - "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, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", - "dev": true, - "requires": {} - }, - "dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "dev": true - }, - "load-json-file": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", - "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "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" - } - }, - "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 - } - } - }, - "@lerna-lite/core": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/core/-/core-3.3.1.tgz", - "integrity": "sha512-YkYVaHzdRqOFKtCZcWfRVg44lu1OXErzx9xKruKYjX6qHfUr0zqyNVm6tbzWGy9wPdU4VWw77KKzG+gtIEcGjA==", - "dev": true, - "requires": { - "@npmcli/run-script": "^7.0.4", - "chalk": "^5.3.0", - "clone-deep": "^4.0.1", - "config-chain": "^1.1.13", - "cosmiconfig": "^9.0.0", - "dedent": "^1.5.1", - "execa": "^8.0.1", - "fs-extra": "^11.2.0", - "glob-parent": "^6.0.2", - "globby": "^14.0.1", - "inquirer": "^9.2.15", - "is-ci": "^3.0.1", - "json5": "^2.2.3", - "load-json-file": "^7.0.1", - "minimatch": "^9.0.3", - "npm-package-arg": "^11.0.1", - "npmlog": "^7.0.1", - "p-map": "^7.0.1", - "p-queue": "^8.0.1", - "resolve-from": "^5.0.0", - "semver": "^7.6.0", - "slash": "^5.1.0", - "strong-log-transformer": "^2.1.0", - "write-file-atomic": "^5.0.1", - "write-json-file": "^5.0.0", - "write-pkg": "^6.0.1" - }, - "dependencies": { - "@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", - "dev": true, - "requires": { - "semver": "^7.3.5" - } - }, - "@npmcli/node-gyp": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", - "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", - "dev": true - }, - "@npmcli/package-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.0.0.tgz", - "integrity": "sha512-OI2zdYBLhQ7kpNPaJxiflofYIpkNLi+lnGdzqUOfRmCF3r2l1nadcjtCYMJKv/Utm/ZtlffaUuTiAktPHbc17g==", - "dev": true, - "requires": { - "@npmcli/git": "^5.0.0", - "glob": "^10.2.2", - "hosted-git-info": "^7.0.0", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^6.0.0", - "proc-log": "^3.0.0", - "semver": "^7.5.3" - } - }, - "@npmcli/run-script": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-7.0.4.tgz", - "integrity": "sha512-9ApYM/3+rBt9V80aYg6tZfzj3UWdiYyCt7gJUD1VJKvWF5nwKDSICXbYIQbspFTq6TOpbsEtIC0LArB8d9PFmg==", - "dev": true, - "requires": { - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/package-json": "^5.0.0", - "@npmcli/promise-spawn": "^7.0.0", - "node-gyp": "^10.0.0", - "which": "^4.0.0" - } - }, - "abbrev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", - "dev": true - }, - "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, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "requires": { - "semver": "^7.0.0" - } - }, - "cacache": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", - "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", - "dev": true, - "requires": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "dependencies": { - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - } - } - }, - "chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true - }, - "cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "dev": true - }, - "cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", - "dev": true, - "requires": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - } - }, - "dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", - "dev": true, - "requires": {} - }, - "detect-indent": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", - "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", - "dev": true - }, - "eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true - }, - "execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - } - }, - "fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "dev": true, - "requires": { - "minipass": "^7.0.3" - } - }, - "get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true - }, - "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globby": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", - "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", - "dev": true, - "requires": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" - } - }, - "hosted-git-info": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", - "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", - "dev": true, - "requires": { - "lru-cache": "^10.0.1" - } - }, - "human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true - }, - "inquirer": { - "version": "9.2.15", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.15.tgz", - "integrity": "sha512-vI2w4zl/mDluHt9YEQ/543VTCwPKWiHzKtm9dM2V0NdFcqEexDAjUHzO1oA60HRNaVifGXXM1tRRNluLVHa0Kg==", - "dev": true, - "requires": { - "@ljharb/through": "^2.3.12", - "ansi-escapes": "^4.3.2", - "chalk": "^5.3.0", - "cli-cursor": "^3.1.0", - "cli-width": "^4.1.0", - "external-editor": "^3.1.0", - "figures": "^3.2.0", - "lodash": "^4.17.21", - "mute-stream": "1.0.0", - "ora": "^5.4.1", - "run-async": "^3.0.0", - "rxjs": "^7.8.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^6.2.0" - } - }, - "is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "requires": { - "ci-info": "^3.2.0" - } - }, - "is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "dev": true - }, - "is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true - }, - "isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", - "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "lines-and-columns": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", - "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", - "dev": true - }, - "load-json-file": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", - "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", - "dev": true - }, - "make-fetch-happen": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", - "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", - "dev": true, - "requires": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" - } - }, - "mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true - }, - "minipass-collect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", - "dev": true, - "requires": { - "minipass": "^7.0.3" - } - }, - "minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", - "dev": true, - "requires": { - "encoding": "^0.1.13", - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - } - }, - "mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", - "dev": true - }, - "node-gyp": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz", - "integrity": "sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==", - "dev": true, - "requires": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^10.3.10", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^13.0.0", - "nopt": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^4.0.0" - } - }, - "nopt": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", - "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", - "dev": true, - "requires": { - "abbrev": "^2.0.0" - } - }, - "normalize-package-data": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.0.tgz", - "integrity": "sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==", - "dev": true, - "requires": { - "hosted-git-info": "^7.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - } - }, - "npm-package-arg": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", - "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", - "dev": true, - "requires": { - "hosted-git-info": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - } - }, - "npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "requires": { - "path-key": "^4.0.0" - } - }, - "onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "requires": { - "mimic-fn": "^4.0.0" - } - }, - "p-map": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.1.tgz", - "integrity": "sha512-2wnaR0XL/FDOj+TgpDuRb2KTjLnu3Fma6b1ZUwGY7LcqenMcvP/YFpjpbPKY6WVGsbuJZRuoUz8iPrt8ORnAFw==", - "dev": true - }, - "p-queue": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.0.1.tgz", - "integrity": "sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==", - "dev": true, - "requires": { - "eventemitter3": "^5.0.1", - "p-timeout": "^6.1.2" - } - }, - "p-timeout": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", - "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", - "dev": true - }, - "path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true - }, - "path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "dev": true - }, - "proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", - "dev": true - }, - "read-pkg": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-8.1.0.tgz", - "integrity": "sha512-PORM8AgzXeskHO/WEv312k9U03B8K9JSiWF/8N9sUuFjBa+9SF2u6K7VClzXwDXab51jCd8Nd36CNM+zR97ScQ==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.1", - "normalize-package-data": "^6.0.0", - "parse-json": "^7.0.0", - "type-fest": "^4.2.0" - }, - "dependencies": { - "parse-json": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.1.tgz", - "integrity": "sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.21.4", - "error-ex": "^1.3.2", - "json-parse-even-better-errors": "^3.0.0", - "lines-and-columns": "^2.0.3", - "type-fest": "^3.8.0" - }, - "dependencies": { - "type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true - } - } - } - } - }, - "run-async": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", - "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", - "dev": true - }, - "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "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 - }, - "slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true - }, - "sort-keys": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.0.0.tgz", - "integrity": "sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==", - "dev": true, - "requires": { - "is-plain-obj": "^4.0.0" - } - }, - "ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", - "dev": true, - "requires": { - "minipass": "^7.0.3" - } - }, - "strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true - }, - "type-fest": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.11.1.tgz", - "integrity": "sha512-MFMf6VkEVZAETidGGSYW2B1MjXbGX+sWIywn2QPEaJ3j08V+MwVRHMXtf2noB8ENJaD0LIun9wh5Z6OPNf1QzQ==", - "dev": true - }, - "typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true, - "optional": true, - "peer": true - }, - "unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", - "dev": true, - "requires": { - "unique-slug": "^4.0.0" - } - }, - "unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", - "dev": true, - "requires": { - "builtins": "^5.0.0" - } - }, - "which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", - "dev": true, - "requires": { - "isexe": "^3.1.1" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - } - }, - "write-json-file": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-5.0.0.tgz", - "integrity": "sha512-ddSsCLa4aQ3kI21BthINo4q905/wfhvQ3JL3774AcRjBaiQmfn5v4rw77jQ7T6CmAit9VOQO+FsLyPkwxoB1fw==", - "dev": true, - "requires": { - "detect-indent": "^7.0.0", - "is-plain-obj": "^4.0.0", - "sort-keys": "^5.0.0", - "write-file-atomic": "^3.0.3" - }, - "dependencies": { - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - } - } - }, - "write-pkg": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-6.0.1.tgz", - "integrity": "sha512-ZwKp0+CQCNrJbhHStRy6IVDnVjvD4gYy6MhQLKgBnl85oaiTNXhvtuox7AqvOSf1wta0YW4U5JidjpJnd1i8TA==", - "dev": true, - "requires": { - "deepmerge-ts": "^5.1.0", - "read-pkg": "^8.1.0", - "sort-keys": "^5.0.0", - "type-fest": "^4.6.0", - "write-json-file": "^5.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "@lerna-lite/filter-packages": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/filter-packages/-/filter-packages-3.3.1.tgz", - "integrity": "sha512-YHK6TazjA2yJsWnsKuHbb8/pobLWjEwv4HaHUU3n9ZiRkfgckRPZV2MYQFfySnTaTJDqUHMVuSmnfaUugTr03w==", - "dev": true, - "requires": { - "@lerna-lite/core": "3.3.1", - "multimatch": "^7.0.0", - "npmlog": "^7.0.1" - }, - "dependencies": { - "array-differ": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-4.0.0.tgz", - "integrity": "sha512-Q6VPTLMsmXZ47ENG3V+wQyZS1ZxXMxFyYzA+Z/GMrJ6yIutAIEf9wTyroTzmGjNfox9/h3GdGBCVh43GVFx4Uw==", - "dev": true - }, - "array-union": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", - "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", - "dev": true - }, - "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, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "multimatch": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-7.0.0.tgz", - "integrity": "sha512-SYU3HBAdF4psHEL/+jXDKHO95/m5P2RvboHT2Y0WtTttvJLP4H/2WS9WlQPFvF6C8d6SpLw8vjCnQOnVIVOSJQ==", - "dev": true, - "requires": { - "array-differ": "^4.0.0", - "array-union": "^3.0.1", - "minimatch": "^9.0.3" - } - } - } - }, - "@lerna-lite/init": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/init/-/init-3.3.1.tgz", - "integrity": "sha512-dYTEfwz4xv43BeILWjWxijhpTcKtHqIQEx1QVEmzOVJu6lbpATkbFYQ5DO4BXElyx/5hjNLHptKnDIen9T5Peg==", - "dev": true, - "requires": { - "@lerna-lite/core": "3.3.1", - "fs-extra": "^11.2.0", - "p-map": "^7.0.1", - "write-json-file": "^5.0.0" - }, - "dependencies": { - "detect-indent": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", - "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", - "dev": true - }, - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "p-map": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.1.tgz", - "integrity": "sha512-2wnaR0XL/FDOj+TgpDuRb2KTjLnu3Fma6b1ZUwGY7LcqenMcvP/YFpjpbPKY6WVGsbuJZRuoUz8iPrt8ORnAFw==", - "dev": true - }, - "sort-keys": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.0.0.tgz", - "integrity": "sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==", - "dev": true, - "requires": { - "is-plain-obj": "^4.0.0" - } - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "write-json-file": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-5.0.0.tgz", - "integrity": "sha512-ddSsCLa4aQ3kI21BthINo4q905/wfhvQ3JL3774AcRjBaiQmfn5v4rw77jQ7T6CmAit9VOQO+FsLyPkwxoB1fw==", - "dev": true, - "requires": { - "detect-indent": "^7.0.0", - "is-plain-obj": "^4.0.0", - "sort-keys": "^5.0.0", - "write-file-atomic": "^3.0.3" - } - } - } - }, - "@lerna-lite/list": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/list/-/list-3.3.1.tgz", - "integrity": "sha512-F5/a2W5PKF2fpLqmLMi58dEdJ2F4mvAlywXA4FRc21T7mYNnJ095oVskruwHlEVZE7jUKitZjM10EVG8sG3HEw==", - "dev": true, - "requires": { - "@lerna-lite/cli": "3.3.1", - "@lerna-lite/core": "3.3.1", - "@lerna-lite/filter-packages": "3.3.1", - "@lerna-lite/listable": "3.3.1" - } - }, - "@lerna-lite/listable": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/listable/-/listable-3.3.1.tgz", - "integrity": "sha512-pMk97xYxPU6opebGHo5m01kr6kbHmoi96SGEM63V9v4UtFrCFQY4UXemrTDZLkzz6WfqaXFLzvx6PGK9lKhnCA==", - "dev": true, - "requires": { - "@lerna-lite/core": "3.3.1", - "chalk": "^5.3.0", - "columnify": "^1.6.0" - }, - "dependencies": { - "chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true - } - } - }, - "@lerna-lite/profiler": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/profiler/-/profiler-3.3.1.tgz", - "integrity": "sha512-EZYu512G+pdgn58BJwBaqfiYMqfhiYKrWNf8bVsEYI8nLSrCgfyq9ZSxMzz+QRx6sv//41KhkACpc2RU9V4yyA==", - "dev": true, - "requires": { - "@lerna-lite/core": "3.3.1", - "fs-extra": "^11.2.0", - "npmlog": "^7.0.1", - "upath": "^2.0.1" - }, - "dependencies": { - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - } - } - }, - "@lerna-lite/run": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/run/-/run-3.3.1.tgz", - "integrity": "sha512-ycuekq6MTPuKOBzwhwcjSX3N1YfjwSH39OyixF8WKmaIoOQM+ogXTU6tjOGcUxVNycNpm1Zx5SgHZmS/APbBKA==", - "dev": true, - "requires": { - "@lerna-lite/cli": "3.3.1", - "@lerna-lite/core": "3.3.1", - "@lerna-lite/filter-packages": "3.3.1", - "@lerna-lite/profiler": "3.3.1", - "chalk": "^5.3.0", - "fs-extra": "^11.2.0", - "npmlog": "^7.0.1", - "p-map": "^7.0.1" - }, - "dependencies": { - "chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true - }, - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "p-map": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.1.tgz", - "integrity": "sha512-2wnaR0XL/FDOj+TgpDuRb2KTjLnu3Fma6b1ZUwGY7LcqenMcvP/YFpjpbPKY6WVGsbuJZRuoUz8iPrt8ORnAFw==", - "dev": true - } - } - }, - "@lerna-lite/version": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@lerna-lite/version/-/version-3.3.1.tgz", - "integrity": "sha512-0Kes5H0H8+tZSTLMTf5ArZTIijROSwgvJsnd5o7z6XvYZM8cq9ED63tpzgX9GKXyqnjZH4mlHpcQr5lpmABJFA==", - "dev": true, - "requires": { - "@lerna-lite/cli": "3.3.1", - "@lerna-lite/core": "3.3.1", - "@octokit/plugin-enterprise-rest": "^6.0.1", - "@octokit/rest": "^20.0.2", - "chalk": "^5.3.0", - "conventional-changelog-angular": "^7.0.0", - "conventional-changelog-core": "^7.0.0", - "conventional-changelog-writer": "^7.0.1", - "conventional-commits-parser": "^5.0.0", - "conventional-recommended-bump": "^9.0.0", - "dedent": "^1.5.1", - "fs-extra": "^11.2.0", - "get-stream": "^8.0.1", - "git-url-parse": "^14.0.0", - "graceful-fs": "^4.2.11", - "is-stream": "^4.0.1", - "load-json-file": "^7.0.1", - "make-dir": "^4.0.0", - "minimatch": "^9.0.3", - "new-github-release-url": "^2.0.0", - "node-fetch": "^3.3.2", - "npm-package-arg": "^11.0.1", - "npmlog": "^7.0.1", - "p-map": "^7.0.1", - "p-pipe": "^4.0.0", - "p-reduce": "^3.0.0", - "pify": "^6.1.0", - "semver": "^7.6.0", - "slash": "^5.1.0", - "temp-dir": "^3.0.0", - "uuid": "^9.0.1", - "write-json-file": "^5.0.0" - }, - "dependencies": { - "@hutson/parse-repository-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-5.0.0.tgz", - "integrity": "sha512-e5+YUKENATs1JgYHMzTr2MW/NDcXGfYFAuOQU8gJgF/kEh4EqKgfGrfLI67bMD4tbhZVlkigz/9YYwWcbOFthg==", - "dev": true - }, - "@octokit/auth-token": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", - "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", - "dev": true - }, - "@octokit/core": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.1.0.tgz", - "integrity": "sha512-BDa2VAMLSh3otEiaMJ/3Y36GU4qf6GI+VivQ/P41NC6GHcdxpKlqV0ikSZ5gdQsmS3ojXeRx5vasgNTinF0Q4g==", - "dev": true, - "requires": { - "@octokit/auth-token": "^4.0.0", - "@octokit/graphql": "^7.0.0", - "@octokit/request": "^8.0.2", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^12.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/endpoint": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.4.tgz", - "integrity": "sha512-DWPLtr1Kz3tv8L0UvXTDP1fNwM0S+z6EJpRcvH66orY6Eld4XBMCSYsaWp4xIm61jTWxK68BrR7ibO+vSDnZqw==", - "dev": true, - "requires": { - "@octokit/types": "^12.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/graphql": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.2.tgz", - "integrity": "sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==", - "dev": true, - "requires": { - "@octokit/request": "^8.0.1", - "@octokit/types": "^12.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/openapi-types": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", - "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", - "dev": true - }, - "@octokit/plugin-paginate-rest": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz", - "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==", - "dev": true, - "requires": { - "@octokit/types": "^12.6.0" - } - }, - "@octokit/plugin-request-log": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.1.tgz", - "integrity": "sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==", - "dev": true, - "requires": {} - }, - "@octokit/plugin-rest-endpoint-methods": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", - "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", - "dev": true, - "requires": { - "@octokit/types": "^12.6.0" - } - }, - "@octokit/request": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.2.0.tgz", - "integrity": "sha512-exPif6x5uwLqv1N1irkLG1zZNJkOtj8bZxuVHd71U5Ftuxf2wGNvAJyNBcPbPC+EBzwYEbBDdSFb8EPcjpYxPQ==", - "dev": true, - "requires": { - "@octokit/endpoint": "^9.0.0", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^12.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request-error": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.1.tgz", - "integrity": "sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==", - "dev": true, - "requires": { - "@octokit/types": "^12.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/rest": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz", - "integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==", - "dev": true, - "requires": { - "@octokit/core": "^5.0.0", - "@octokit/plugin-paginate-rest": "^9.0.0", - "@octokit/plugin-request-log": "^4.0.0", - "@octokit/plugin-rest-endpoint-methods": "^10.0.0" - } - }, - "@octokit/types": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", - "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", - "dev": true, - "requires": { - "@octokit/openapi-types": "^20.0.0" - } - }, - "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, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "requires": { - "semver": "^7.0.0" - } - }, - "chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true - }, - "conventional-changelog-angular": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", - "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", - "dev": true, - "requires": { - "compare-func": "^2.0.0" - } - }, - "conventional-changelog-core": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-7.0.0.tgz", - "integrity": "sha512-UYgaB1F/COt7VFjlYKVE/9tTzfU3VUq47r6iWf6lM5T7TlOxr0thI63ojQueRLIpVbrtHK4Ffw+yQGduw2Bhdg==", - "dev": true, - "requires": { - "@hutson/parse-repository-url": "^5.0.0", - "add-stream": "^1.0.0", - "conventional-changelog-writer": "^7.0.0", - "conventional-commits-parser": "^5.0.0", - "git-raw-commits": "^4.0.0", - "git-semver-tags": "^7.0.0", - "hosted-git-info": "^7.0.0", - "normalize-package-data": "^6.0.0", - "read-pkg": "^8.0.0", - "read-pkg-up": "^10.0.0" - } - }, - "conventional-changelog-preset-loader": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-4.1.0.tgz", - "integrity": "sha512-HozQjJicZTuRhCRTq4rZbefaiCzRM2pr6u2NL3XhrmQm4RMnDXfESU6JKu/pnKwx5xtdkYfNCsbhN5exhiKGJA==", - "dev": true - }, - "conventional-changelog-writer": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-7.0.1.tgz", - "integrity": "sha512-Uo+R9neH3r/foIvQ0MKcsXkX642hdm9odUp7TqgFS7BsalTcjzRlIfWZrZR1gbxOozKucaKt5KAbjW8J8xRSmA==", - "dev": true, - "requires": { - "conventional-commits-filter": "^4.0.0", - "handlebars": "^4.7.7", - "json-stringify-safe": "^5.0.1", - "meow": "^12.0.1", - "semver": "^7.5.2", - "split2": "^4.0.0" - } - }, - "conventional-commits-filter": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-4.0.0.tgz", - "integrity": "sha512-rnpnibcSOdFcdclpFwWa+pPlZJhXE7l+XK04zxhbWrhgpR96h33QLz8hITTXbcYICxVr3HZFtbtUAQ+4LdBo9A==", - "dev": true - }, - "conventional-commits-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", - "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", - "dev": true, - "requires": { - "is-text-path": "^2.0.0", - "JSONStream": "^1.3.5", - "meow": "^12.0.1", - "split2": "^4.0.0" - } - }, - "conventional-recommended-bump": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-9.0.0.tgz", - "integrity": "sha512-HR1yD0G5HgYAu6K0wJjLd7QGRK8MQDqqj6Tn1n/ja1dFwBCE6QmV+iSgQ5F7hkx7OUR/8bHpxJqYtXj2f/opPQ==", - "dev": true, - "requires": { - "conventional-changelog-preset-loader": "^4.1.0", - "conventional-commits-filter": "^4.0.0", - "conventional-commits-parser": "^5.0.0", - "git-raw-commits": "^4.0.0", - "git-semver-tags": "^7.0.0", - "meow": "^12.0.1" - } - }, - "dargs": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", - "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", - "dev": true - }, - "dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", - "dev": true, - "requires": {} - }, - "detect-indent": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", - "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", - "dev": true - }, - "find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, - "requires": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - } - }, - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true - }, - "git-raw-commits": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", - "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", - "dev": true, - "requires": { - "dargs": "^8.0.0", - "meow": "^12.0.1", - "split2": "^4.0.0" - } - }, - "git-semver-tags": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-7.0.1.tgz", - "integrity": "sha512-NY0ZHjJzyyNXHTDZmj+GG7PyuAKtMsyWSwh07CR2hOZFa+/yoTsXci/nF2obzL8UDhakFNkD9gNdt/Ed+cxh2Q==", - "dev": true, - "requires": { - "meow": "^12.0.1", - "semver": "^7.5.2" - } - }, - "git-url-parse": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-14.0.0.tgz", - "integrity": "sha512-NnLweV+2A4nCvn4U/m2AoYu0pPKlsmhK9cknG7IMwsjFY1S2jxM+mAhsDxyxfCIGfGaD+dozsyX4b6vkYc83yQ==", - "dev": true, - "requires": { - "git-up": "^7.0.0" - } - }, - "hosted-git-info": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", - "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", - "dev": true, - "requires": { - "lru-cache": "^10.0.1" - } - }, - "is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "dev": true - }, - "is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", - "dev": true - }, - "is-text-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", - "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", - "dev": true, - "requires": { - "text-extensions": "^2.0.0" - } - }, - "json-parse-even-better-errors": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", - "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "lines-and-columns": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", - "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", - "dev": true - }, - "load-json-file": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", - "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", - "dev": true - }, - "locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "requires": { - "p-locate": "^6.0.0" - } - }, - "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, - "requires": { - "semver": "^7.5.3" - } - }, - "meow": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", - "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", - "dev": true - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "dev": true, - "requires": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - } - }, - "normalize-package-data": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.0.tgz", - "integrity": "sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==", - "dev": true, - "requires": { - "hosted-git-info": "^7.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - } - }, - "npm-package-arg": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", - "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", - "dev": true, - "requires": { - "hosted-git-info": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - } - }, - "p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "requires": { - "yocto-queue": "^1.0.0" - } - }, - "p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, - "requires": { - "p-limit": "^4.0.0" - } - }, - "p-map": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.1.tgz", - "integrity": "sha512-2wnaR0XL/FDOj+TgpDuRb2KTjLnu3Fma6b1ZUwGY7LcqenMcvP/YFpjpbPKY6WVGsbuJZRuoUz8iPrt8ORnAFw==", - "dev": true - }, - "p-pipe": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-4.0.0.tgz", - "integrity": "sha512-HkPfFklpZQPUKBFXzKFB6ihLriIHxnmuQdK9WmLDwe4hf2PdhhfWT/FJa+pc3bA1ywvKXtedxIRmd4Y7BTXE4w==", - "dev": true - }, - "p-reduce": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-3.0.0.tgz", - "integrity": "sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==", - "dev": true - }, - "parse-json": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.1.tgz", - "integrity": "sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.21.4", - "error-ex": "^1.3.2", - "json-parse-even-better-errors": "^3.0.0", - "lines-and-columns": "^2.0.3", - "type-fest": "^3.8.0" - }, - "dependencies": { - "type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true - } - } - }, - "path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true - }, - "pify": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-6.1.0.tgz", - "integrity": "sha512-KocF8ve28eFjjuBKKGvzOBGzG8ew2OqOOSxTTZhirkzH7h3BI1vyzqlR0qbfcDBve1Yzo3FVlWUAtCRrbVN8Fw==", - "dev": true - }, - "proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", - "dev": true - }, - "read-pkg": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-8.1.0.tgz", - "integrity": "sha512-PORM8AgzXeskHO/WEv312k9U03B8K9JSiWF/8N9sUuFjBa+9SF2u6K7VClzXwDXab51jCd8Nd36CNM+zR97ScQ==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.1", - "normalize-package-data": "^6.0.0", - "parse-json": "^7.0.0", - "type-fest": "^4.2.0" - } - }, - "read-pkg-up": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-10.1.0.tgz", - "integrity": "sha512-aNtBq4jR8NawpKJQldrQcSW9y/d+KWH4v24HWkHljOZ7H0av+YTGANBzRh9A5pw7v/bLVsLVPpOhJ7gHNVy8lA==", - "dev": true, - "requires": { - "find-up": "^6.3.0", - "read-pkg": "^8.1.0", - "type-fest": "^4.2.0" - } - }, - "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true - }, - "sort-keys": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.0.0.tgz", - "integrity": "sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==", - "dev": true, - "requires": { - "is-plain-obj": "^4.0.0" - } - }, - "split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "dev": true - }, - "temp-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", - "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", - "dev": true - }, - "text-extensions": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", - "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", - "dev": true - }, - "type-fest": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.11.1.tgz", - "integrity": "sha512-MFMf6VkEVZAETidGGSYW2B1MjXbGX+sWIywn2QPEaJ3j08V+MwVRHMXtf2noB8ENJaD0LIun9wh5Z6OPNf1QzQ==", - "dev": true - }, - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true - }, - "validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", - "dev": true, - "requires": { - "builtins": "^5.0.0" - } - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "write-json-file": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-5.0.0.tgz", - "integrity": "sha512-ddSsCLa4aQ3kI21BthINo4q905/wfhvQ3JL3774AcRjBaiQmfn5v4rw77jQ7T6CmAit9VOQO+FsLyPkwxoB1fw==", - "dev": true, - "requires": { - "detect-indent": "^7.0.0", - "is-plain-obj": "^4.0.0", - "sort-keys": "^5.0.0", - "write-file-atomic": "^3.0.3" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", - "dev": true - } - } - }, - "@ljharb/through": { - "version": "2.3.12", - "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.12.tgz", - "integrity": "sha512-ajo/heTlG3QgC8EGP6APIejksVAYt4ayz4tqoP3MolFELzcH1x1fzwEYRJTPO0IELutZ5HQ0c26/GqAYy79u3g==", - "dev": true, - "requires": { - "call-bind": "^1.0.5" - } - }, - "@napi-rs/cli": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.16.2.tgz", - "integrity": "sha512-U2aZfnr0s9KkXpZlYC0l5WxWCXL7vJUNpCnWMwq3T9GG9rhYAAUM9CTZsi1Z+0iR2LcHbfq9EfMgoqnuTyUjfg==", - "dev": true - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@npmcli/agent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.1.tgz", - "integrity": "sha512-H4FrOVtNyWC8MUwL3UfjOsAihHvT1Pe8POj3JvjXhSTJipsZMtgUALCT4mGyYZNxymkUfOw3PUj6dE4QPp6osQ==", - "requires": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.1" - }, - "dependencies": { - "agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "requires": { - "debug": "^4.3.4" - } - }, - "http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - }, - "socks-proxy-agent": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", - "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", - "requires": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "socks": "^2.7.1" - } - } - } - }, - "@npmcli/fs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.0.tgz", - "integrity": "sha512-VhP1qZLXcrXRIaPoqb4YA55JQxLNF3jNR4T55IdOJa3+IFJKNYHtPvtXx8slmeMavj37vCzCfrqQM1vWLsYKLA==", - "dev": true, - "requires": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "@npmcli/git": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-5.0.4.tgz", - "integrity": "sha512-nr6/WezNzuYUppzXRaYu/W4aT5rLxdXqEFupbh6e/ovlYFQ8hpu1UUPV3Ir/YTl+74iXl2ZOMlGzudh9ZPUchQ==", - "requires": { - "@npmcli/promise-spawn": "^7.0.0", - "lru-cache": "^10.0.1", - "npm-pick-manifest": "^9.0.0", - "proc-log": "^3.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^4.0.0" - }, - "dependencies": { - "builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "requires": { - "semver": "^7.0.0" - } - }, - "hosted-git-info": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", - "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", - "requires": { - "lru-cache": "^10.0.1" - } - }, - "isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==" - }, - "npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==" - }, - "npm-package-arg": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", - "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", - "requires": { - "hosted-git-info": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - } - }, - "npm-pick-manifest": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.0.0.tgz", - "integrity": "sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg==", - "requires": { - "npm-install-checks": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "npm-package-arg": "^11.0.0", - "semver": "^7.3.5" - } - }, - "proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==" - }, - "validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", - "requires": { - "builtins": "^5.0.0" - } - }, - "which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", - "requires": { - "isexe": "^3.1.1" - } - } - } - }, - "@npmcli/installed-package-contents": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz", - "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", - "dev": true, - "requires": { - "npm-bundled": "^1.1.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "@npmcli/map-workspaces": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-2.0.4.tgz", - "integrity": "sha512-bMo0aAfwhVwqoVM5UzX1DJnlvVvzDCHae821jv48L1EsrYwfOZChlqWYXEtto/+BkBXetPbEWgau++/brh4oVg==", - "dev": true, - "requires": { - "@npmcli/name-from-folder": "^1.0.1", - "glob": "^8.0.1", - "minimatch": "^5.0.1", - "read-package-json-fast": "^2.0.3" - }, - "dependencies": { - "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, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "read-package-json-fast": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", - "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", - "dev": true, - "requires": { - "json-parse-even-better-errors": "^2.3.0", - "npm-normalize-package-bin": "^1.0.1" - } - } - } - }, - "@npmcli/metavuln-calculator": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-3.1.1.tgz", - "integrity": "sha512-n69ygIaqAedecLeVH3KnO39M6ZHiJ2dEv5A7DGvcqCB8q17BGUgW8QaanIkbWUo2aYGZqJaOORTLAlIvKjNDKA==", - "dev": true, - "requires": { - "cacache": "^16.0.0", - "json-parse-even-better-errors": "^2.3.1", - "pacote": "^13.0.3", - "semver": "^7.3.5" - }, - "dependencies": { - "@npmcli/git": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-3.0.2.tgz", - "integrity": "sha512-CAcd08y3DWBJqJDpfuVL0uijlq5oaXaOJEKHKc4wqrjd00gkvTZB+nFuLn+doOOKddaQS9JfqtNoFCO2LCvA3w==", - "dev": true, - "requires": { - "@npmcli/promise-spawn": "^3.0.0", - "lru-cache": "^7.4.4", - "mkdirp": "^1.0.4", - "npm-pick-manifest": "^7.0.0", - "proc-log": "^2.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^2.0.2" - } - }, - "@npmcli/promise-spawn": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-3.0.0.tgz", - "integrity": "sha512-s9SgS+p3a9Eohe68cSI3fi+hpcZUmXq5P7w0kMlAsWVtR7XbK3ptkZqKT2cK1zLDObJ3sR+8P59sJE0w/KTL1g==", - "dev": true, - "requires": { - "infer-owner": "^1.0.4" - } - }, - "builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "requires": { - "semver": "^7.0.0" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "hosted-git-info": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz", - "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==", - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - } - }, - "lru-cache": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz", - "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==", - "dev": true - }, - "minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "requires": { - "encoding": "^0.1.13", - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - } - }, - "npm-package-arg": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", - "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", - "dev": true, - "requires": { - "hosted-git-info": "^5.0.0", - "proc-log": "^2.0.1", - "semver": "^7.3.5", - "validate-npm-package-name": "^4.0.0" - } - }, - "npm-registry-fetch": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-13.3.1.tgz", - "integrity": "sha512-eukJPi++DKRTjSBRcDZSDDsGqRK3ehbxfFUcgaRd0Yp6kRwOwh2WVn0r+8rMB4nnuzvAk6rQVzl6K5CkYOmnvw==", - "dev": true, - "requires": { - "make-fetch-happen": "^10.0.6", - "minipass": "^3.1.6", - "minipass-fetch": "^2.0.3", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.1.2", - "npm-package-arg": "^9.0.1", - "proc-log": "^2.0.0" - } - }, - "pacote": { - "version": "13.6.2", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-13.6.2.tgz", - "integrity": "sha512-Gu8fU3GsvOPkak2CkbojR7vjs3k3P9cA6uazKTHdsdV0gpCEQq2opelnEv30KRQWgVzP5Vd/5umjcedma3MKtg==", - "dev": true, - "requires": { - "@npmcli/git": "^3.0.0", - "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/promise-spawn": "^3.0.0", - "@npmcli/run-script": "^4.1.0", - "cacache": "^16.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "infer-owner": "^1.0.4", - "minipass": "^3.1.6", - "mkdirp": "^1.0.4", - "npm-package-arg": "^9.0.0", - "npm-packlist": "^5.1.0", - "npm-pick-manifest": "^7.0.0", - "npm-registry-fetch": "^13.0.1", - "proc-log": "^2.0.0", - "promise-retry": "^2.0.1", - "read-package-json": "^5.0.0", - "read-package-json-fast": "^2.0.3", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11" - } - }, - "read-package-json-fast": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", - "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", - "dev": true, - "requires": { - "json-parse-even-better-errors": "^2.3.0", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "validate-npm-package-name": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz", - "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", - "dev": true, - "requires": { - "builtins": "^5.0.0" - } - } - } - }, - "@npmcli/name-from-folder": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz", - "integrity": "sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA==", - "dev": true - }, - "@npmcli/node-gyp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-2.0.0.tgz", - "integrity": "sha512-doNI35wIe3bBaEgrlPfdJPaCpUR89pJWep4Hq3aRdh6gKazIVWfs0jHttvSSoq47ZXgC7h73kDsUl8AoIQUB+A==", - "dev": true - }, - "@npmcli/package-json": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-2.0.0.tgz", - "integrity": "sha512-42jnZ6yl16GzjWSH7vtrmWyJDGVa/LXPdpN2rcUWolFjc9ON2N3uz0qdBbQACfmhuJZ2lbKYtmK5qx68ZPLHMA==", - "dev": true, - "requires": { - "json-parse-even-better-errors": "^2.3.1" - } - }, - "@npmcli/promise-spawn": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.1.tgz", - "integrity": "sha512-P4KkF9jX3y+7yFUxgcUdDtLy+t4OlDGuEBLNs57AZsfSfg+uV6MLndqGpnl4831ggaEdXwR50XFoZP4VFtHolg==", - "requires": { - "which": "^4.0.0" - }, - "dependencies": { - "isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==" - }, - "which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", - "requires": { - "isexe": "^3.1.1" - } - } - } - }, - "@npmcli/run-script": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-4.2.1.tgz", - "integrity": "sha512-7dqywvVudPSrRCW5nTHpHgeWnbBtz8cFkOuKrecm6ih+oO9ciydhWt6OF7HlqupRRmB8Q/gECVdB9LMfToJbRg==", - "dev": true, - "requires": { - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/promise-spawn": "^3.0.0", - "node-gyp": "^9.0.0", - "read-package-json-fast": "^2.0.3", - "which": "^2.0.2" - }, - "dependencies": { - "@npmcli/promise-spawn": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-3.0.0.tgz", - "integrity": "sha512-s9SgS+p3a9Eohe68cSI3fi+hpcZUmXq5P7w0kMlAsWVtR7XbK3ptkZqKT2cK1zLDObJ3sR+8P59sJE0w/KTL1g==", - "dev": true, - "requires": { - "infer-owner": "^1.0.4" - } - }, - "read-package-json-fast": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", - "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", - "dev": true, - "requires": { - "json-parse-even-better-errors": "^2.3.0", - "npm-normalize-package-bin": "^1.0.1" - } - } - } - }, - "@octokit/plugin-enterprise-rest": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz", - "integrity": "sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==", - "dev": true - }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "optional": true - }, - "@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "dev": true, - "peer": true - }, - "@sigstore/bundle": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.2.0.tgz", - "integrity": "sha512-5VI58qgNs76RDrwXNhpmyN/jKpq9evV/7f1XrcqcAfvxDl5SeVY/I5Rmfe96ULAV7/FK5dge9RBKGBJPhL1WsQ==", - "requires": { - "@sigstore/protobuf-specs": "^0.3.0" - } - }, - "@sigstore/core": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-1.0.0.tgz", - "integrity": "sha512-dW2qjbWLRKGu6MIDUTBuJwXCnR8zivcSpf5inUzk7y84zqy/dji0/uahppoIgMoKeR+6pUZucrwHfkQQtiG9Rw==" - }, - "@sigstore/protobuf-specs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.3.0.tgz", - "integrity": "sha512-zxiQ66JFOjVvP9hbhGj/F/qNdsZfkGb/dVXSanNRNuAzMlr4MC95voPUBX8//ZNnmv3uSYzdfR/JSkrgvZTGxA==" - }, - "@sigstore/sign": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-2.2.3.tgz", - "integrity": "sha512-LqlA+ffyN02yC7RKszCdMTS6bldZnIodiox+IkT8B2f8oRYXCB3LQ9roXeiEL21m64CVH1wyveYAORfD65WoSw==", - "requires": { - "@sigstore/bundle": "^2.2.0", - "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.0", - "make-fetch-happen": "^13.0.0" - }, - "dependencies": { - "@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", - "requires": { - "semver": "^7.3.5" - } - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "cacache": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", - "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", - "requires": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - } - }, - "fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "requires": { - "minipass": "^7.0.3" - } - }, - "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - } - }, - "make-fetch-happen": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", - "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", - "requires": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" - }, - "minipass-collect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", - "requires": { - "minipass": "^7.0.3" - } - }, - "minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", - "requires": { - "encoding": "^0.1.13", - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - } - }, - "ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", - "requires": { - "minipass": "^7.0.3" - } - }, - "unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", - "requires": { - "unique-slug": "^4.0.0" - } - }, - "unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", - "requires": { - "imurmurhash": "^0.1.4" - } - } - } - }, - "@sigstore/tuf": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-2.3.1.tgz", - "integrity": "sha512-9Iv40z652td/QbV0o5n/x25H9w6IYRt2pIGbTX55yFDYlApDQn/6YZomjz6+KBx69rXHLzHcbtTS586mDdFD+Q==", - "requires": { - "@sigstore/protobuf-specs": "^0.3.0", - "tuf-js": "^2.2.0" - } - }, - "@sigstore/verify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-1.1.0.tgz", - "integrity": "sha512-1fTqnqyTBWvV7cftUUFtDcHPdSox0N3Ub7C0lRyReYx4zZUlNTZjCV+HPy4Lre+r45dV7Qx5JLKvqqsgxuyYfg==", - "requires": { - "@sigstore/bundle": "^2.2.0", - "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.0" - } - }, - "@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true - }, - "@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^3.0.0" - } - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true, - "optional": true, - "peer": true - }, - "@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "optional": true, - "peer": true - }, - "@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "optional": true, - "peer": true - }, - "@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, - "optional": true, - "peer": true - }, - "@tufjs/canonical-json": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", - "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==" - }, - "@tufjs/models": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-2.0.0.tgz", - "integrity": "sha512-c8nj8BaOExmZKO2DXhDfegyhSGcG9E/mPN3U13L+/PsoWm1uaGiHHjxqSHQiasDBQwDA3aHuw9+9spYAP1qvvg==", - "requires": { - "@tufjs/canonical-json": "2.0.0", - "minimatch": "^9.0.3" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "@types/babel__core": { - "version": "7.1.19", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", - "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@types/babel__traverse": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.2.tgz", - "integrity": "sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==", - "dev": true, - "requires": { - "@babel/types": "^7.3.0" - } - }, - "@types/cross-spawn": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.3.tgz", - "integrity": "sha512-BDAkU7WHHRHnvBf5z89lcvACsvkz/n7Tv+HyD/uW76O29HoH1Tk/W6iQrepaZVbisvlEek4ygwT8IW7ow9XLAA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/diff": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.0.2.tgz", - "integrity": "sha512-uw8eYMIReOwstQ0QKF0sICefSy8cNO/v7gOTiIy9SbwuHyEecJUm7qlgueOO5S1udZ5I/irVydHVwMchgzbKTg==", - "dev": true - }, - "@types/find-up": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@types/find-up/-/find-up-2.1.1.tgz", - "integrity": "sha512-60LC501bQRN9/3yfVaEEMd7IndaufffL56PBRAejPpUrY304Ps1jfnjNqPw5jmM5R8JHWiKBAe5IHzNcPV41AA==", - "dev": true - }, - "@types/fs-extra": { - "version": "9.0.13", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", - "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "requires": { - "@types/istanbul-lib-report": "*" - } - }, - "@types/jest": { - "version": "29.5.6", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.6.tgz", - "integrity": "sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w==", - "dev": true, - "requires": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "@types/jquery": { - "version": "3.5.30", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.30.tgz", - "integrity": "sha512-nbWKkkyb919DOUxjmRVk8vwtDb0/k8FKncmUKFi+NY+QXqWltooxTrswvz4LspQwxvLdvzBN1TImr6cw3aQx2A==", - "dev": true, - "requires": { - "@types/sizzle": "*" - } - }, - "@types/js-yaml": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", - "integrity": "sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==", - "dev": true - }, - "@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "@types/jsonfile": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", - "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/jstree": { - "version": "3.3.46", - "resolved": "https://registry.npmjs.org/@types/jstree/-/jstree-3.3.46.tgz", - "integrity": "sha512-Xj+lbRetEsI1TkP2cmQuCDSCT7qD3OUUCtok/8q2f2hx4PCXkBdjRO7AnS8CNj/tKsqjjZ0Pq6cNfyRcqDumsw==", - "dev": true, - "requires": { - "@types/jquery": "*" - } - }, - "@types/lodash": { - "version": "4.14.178", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz", - "integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==", - "dev": true - }, - "@types/lodash-deep": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/lodash-deep/-/lodash-deep-2.0.2.tgz", - "integrity": "sha512-q/9X4upLiTPmepS9JSYvjcWXWVZtqP/G4bFz9/JHEVR9MmNQhYn9+d9a4SDa2kzFNGzkG5O8vXJlbeWFN0a0kQ==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", - "dev": true - }, - "@types/mustache": { - "version": "0.8.32", - "resolved": "https://registry.npmjs.org/@types/mustache/-/mustache-0.8.32.tgz", - "integrity": "sha512-RTVWV485OOf4+nO2+feurk0chzHkSjkjALiejpHltyuMf/13fGymbbNNFrSKdSSUg1TIwzszXdWsVirxgqYiFA==", - "dev": true - }, - "@types/node": { - "version": "14.18.63", - "resolved": "https://zowe.jfrog.io/zowe/api/npm/npm-release/@types/node/-/node-14.18.63.tgz", - "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", - "dev": true - }, - "@types/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", - "dev": true, - "requires": { - "@types/node": "*", - "form-data": "^4.0.0" - } - }, - "@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "@types/npm-package-arg": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@types/npm-package-arg/-/npm-package-arg-6.1.2.tgz", - "integrity": "sha512-K7TdZq7dTZKKgxaFGLR6VPAeNMDM7GwTELlVNyzQ0KKc6Du3+SYYRXFNEDrsCptpEpMjMNKVlb/5/ZNS/MeHjw==", - "dev": true - }, - "@types/npm-registry-fetch": { - "version": "8.0.7", - "resolved": "https://registry.npmjs.org/@types/npm-registry-fetch/-/npm-registry-fetch-8.0.7.tgz", - "integrity": "sha512-db9iBh7kDDg4lRT4k4XZ6IiecTEgFCID4qk+VDVPbtzU855q3KZLCn08ATr4H27ntRJVhulQ7GWjl24H42x96w==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/node-fetch": "*", - "@types/npm-package-arg": "*", - "@types/npmlog": "*", - "@types/ssri": "*" - } - }, - "@types/npmlog": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@types/npmlog/-/npmlog-7.0.0.tgz", - "integrity": "sha512-hJWbrKFvxKyWwSUXjZMYTINsSOY6IclhvGOZ97M8ac2tmR9hMwmTnYaMdpGhvju9ctWLTPhCS+eLfQNluiEjQQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/pacote": { - "version": "11.1.8", - "resolved": "https://registry.npmjs.org/@types/pacote/-/pacote-11.1.8.tgz", - "integrity": "sha512-/XLR0VoTh2JEO0jJg1q/e6Rh9bxjBq9vorJuQmtT7rRrXSiWz7e7NsvXVYJQ0i8JxMlBMPPYDTnrRe7MZRFA8Q==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/npm-registry-fetch": "*", - "@types/npmlog": "*", - "@types/ssri": "*" - } - }, - "@types/progress": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/progress/-/progress-2.0.5.tgz", - "integrity": "sha512-ZYYVc/kSMkhH9W/4dNK/sLNra3cnkfT2nJyOAIDY+C2u6w72wa0s1aXAezVtbTsnN8HID1uhXCrLwDE2ZXpplg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/readline-sync": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/@types/readline-sync/-/readline-sync-1.4.5.tgz", - "integrity": "sha512-vD/LCH84gWf9CoJaqGL8Ey0/oFrgHNEf/R/SPzoDeZa5Zr8Fh5tPCaTF2UC/m1shAcAHVHHZmDQrsoWMkCj0gA==", - "dev": true - }, - "@types/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ==", - "dev": true, - "requires": { - "@types/glob": "*", - "@types/node": "*" - } - }, - "@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, - "@types/sizzle": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.4.tgz", - "integrity": "sha512-jA2llq2zNkg8HrALI7DtWzhALcVH0l7i89yhY3iBdOz6cBPeACoFq+fkQrjHA39t1hnSFOboZ7A/AY5MMZSlag==", - "dev": true - }, - "@types/ssh2": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.11.6.tgz", - "integrity": "sha512-8Mf6bhzYYBLEB/G6COux7DS/F5bCWwojv/qFo2yH/e4cLzAavJnxvFXrYW59iKfXdhG6OmzJcXDasgOb/s0rxw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/ssri": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/@types/ssri/-/ssri-7.1.5.tgz", - "integrity": "sha512-odD/56S3B51liILSk5aXJlnYt99S6Rt9EFDDqGtJM26rKHApHcwyU/UoYHrzKkdkHMAIquGWCuHtQTbes+FRQw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/stack-trace": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/stack-trace/-/stack-trace-0.0.29.tgz", - "integrity": "sha512-TgfOX+mGY/NyNxJLIbDWrO9DjGoVSW9+aB8H2yy1fy32jsvxijhmyJI9fDFgvz3YP4lvJaq9DzdR/M1bOgVc9g==", - "dev": true - }, - "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "@types/tar": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/@types/tar/-/tar-6.1.3.tgz", - "integrity": "sha512-YzDOr5kdAeqS8dcO6NTTHTMJ44MUCBDoLEIyPtwEn7PssKqUYL49R1iCVJPeiPzPlKi6DbH33eZkpeJ27e4vHg==", - "dev": true, - "requires": { - "@types/node": "*", - "minipass": "^3.3.5" - } - }, - "@types/uuid": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", - "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", - "dev": true - }, - "@types/which": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/which/-/which-2.0.1.tgz", - "integrity": "sha512-Jjakcv8Roqtio6w1gr0D7y6twbhx6gGgFGF5BLwajPpnOIOxFkakFhCq+LmyyeAz7BX6ULrjBOxdKaCDy+4+dQ==", - "dev": true - }, - "@types/yargs": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.4.tgz", - "integrity": "sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A==", - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "20.2.1", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", - "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==" - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.1.tgz", - "integrity": "sha512-FsWboKkWdytGiXT5O1/R9j37YgcjO8MKHSUmWnIEjVaz0krHkplPnYi7mwdb+5+cs0toFNQb0HIrN7zONdIEWg==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.40.1", - "@typescript-eslint/type-utils": "5.40.1", - "@typescript-eslint/utils": "5.40.1", - "debug": "^4.3.4", - "ignore": "^5.2.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/parser": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.40.1.tgz", - "integrity": "sha512-IK6x55va5w4YvXd4b3VrXQPldV9vQTxi5ov+g4pMANsXPTXOcfjx08CRR1Dfrcc51syPtXHF5bgLlMHYFrvQtg==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.40.1", - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/typescript-estree": "5.40.1", - "debug": "^4.3.4" - }, - "dependencies": { - "@typescript-eslint/types": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.1.tgz", - "integrity": "sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz", - "integrity": "sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/visitor-keys": "5.40.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz", - "integrity": "sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.40.1", - "eslint-visitor-keys": "^3.3.0" - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - } - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.40.1.tgz", - "integrity": "sha512-jkn4xsJiUQucI16OLCXrLRXDZ3afKhOIqXs4R3O+M00hdQLKR58WuyXPZZjhKLFCEP2g+TXdBRtLQ33UfAdRUg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/visitor-keys": "5.40.1" - }, - "dependencies": { - "@typescript-eslint/types": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.1.tgz", - "integrity": "sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw==", - "dev": true - }, - "@typescript-eslint/visitor-keys": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz", - "integrity": "sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.40.1", - "eslint-visitor-keys": "^3.3.0" - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - } - } - }, - "@typescript-eslint/type-utils": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.40.1.tgz", - "integrity": "sha512-DLAs+AHQOe6n5LRraXiv27IYPhleF0ldEmx6yBqBgBLaNRKTkffhV1RPsjoJBhVup2zHxfaRtan8/YRBgYhU9Q==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "5.40.1", - "@typescript-eslint/utils": "5.40.1", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "dependencies": { - "@typescript-eslint/types": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.1.tgz", - "integrity": "sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz", - "integrity": "sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/visitor-keys": "5.40.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz", - "integrity": "sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.40.1", - "eslint-visitor-keys": "^3.3.0" - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - } - } - }, - "@typescript-eslint/types": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", - "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz", - "integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/visitor-keys": "4.33.0", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.40.1.tgz", - "integrity": "sha512-a2TAVScoX9fjryNrW6BZRnreDUszxqm9eQ9Esv8n5nXApMW0zeANUYlwh/DED04SC/ifuBvXgZpIK5xeJHQ3aw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.40.1", - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/typescript-estree": "5.40.1", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", - "semver": "^7.3.7" - }, - "dependencies": { - "@typescript-eslint/types": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.1.tgz", - "integrity": "sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz", - "integrity": "sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.40.1", - "@typescript-eslint/visitor-keys": "5.40.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz", - "integrity": "sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.40.1", - "eslint-visitor-keys": "^3.3.0" - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - } - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", - "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.33.0", - "eslint-visitor-keys": "^2.0.0" - } - }, - "@zkochan/rimraf": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@zkochan/rimraf/-/rimraf-2.1.2.tgz", - "integrity": "sha512-Lc2oK51J6aQWcLWTloobJun5ZF41BbTDdLvE+aMcexoVWFoFqvZmnZoyXR2IZk6NJEVoZW8tjgtvQLfTsmRs2Q==", - "dev": true, - "requires": { - "rimraf": "^3.0.2" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "@zowe/cli": { - "version": "file:packages/cli", - "requires": { - "@types/diff": "^5.0.2", - "@types/lodash": "^4.14.175", - "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1", - "@zowe/provisioning-for-zowe-sdk": "7.29.2", - "@zowe/secrets-for-zowe-sdk": "7.18.6", - "@zowe/zos-console-for-zowe-sdk": "7.29.2", - "@zowe/zos-files-for-zowe-sdk": "7.29.2", - "@zowe/zos-jobs-for-zowe-sdk": "7.29.2", - "@zowe/zos-logs-for-zowe-sdk": "7.29.2", - "@zowe/zos-tso-for-zowe-sdk": "7.29.2", - "@zowe/zos-uss-for-zowe-sdk": "7.29.2", - "@zowe/zos-workflows-for-zowe-sdk": "7.29.2", - "@zowe/zosmf-for-zowe-sdk": "7.29.2", - "comment-json": "^4.1.1", - "find-process": "1.4.7", - "get-stream": "6.0.1", - "lodash": "4.17.21", - "minimatch": "5.0.1", - "strip-ansi": "^6.0.1", - "tar": "6.2.1", - "which": "^2.0.2" - }, - "dependencies": { - "@zowe/secrets-for-zowe-sdk": { - "version": "7.18.6", - "resolved": "https://zowe.jfrog.io/zowe/api/npm/npm-local-release/@zowe/secrets-for-zowe-sdk/-/@zowe/secrets-for-zowe-sdk-7.18.6.tgz", - "integrity": "sha512-3ElVUd5VYWUxVjXRCeM/jmXh9u1rnWtxobQEpgEZ2iNt+PTt3QajIxUH9MxriELVCp7u39AeAG4lfxs3wnrGzA==", - "optional": true - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "@zowe/cli-test-utils": { - "version": "file:__tests__/__packages__/cli-test-utils", - "requires": { - "@types/js-yaml": "^4.0.0", - "@types/uuid": "^8.3.0", - "@zowe/imperative": "5.27.1", - "find-up": "^5.0.0", - "js-yaml": "^4.0.0", - "rimraf": "^3.0.2", - "uuid": "^8.3.2" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "@zowe/core-for-zowe-sdk": { - "version": "file:packages/core", - "requires": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/imperative": "5.27.1", - "comment-json": "4.1.1", - "string-width": "4.2.3" - } - }, - "@zowe/imperative": { - "version": "file:packages/imperative", - "requires": { - "@types/cross-spawn": "^6.0.2", - "@types/diff": "^5.0.2", - "@types/find-up": "^2.1.1", - "@types/fs-extra": "^9.0.13", - "@types/glob": "^7.1.1", - "@types/jsonfile": "^6.1.0", - "@types/lodash": "^4.14.165", - "@types/lodash-deep": "^2.0.0", - "@types/mustache": "^0.8.32", - "@types/npm-package-arg": "^6.1.0", - "@types/pacote": "^11.1.0", - "@types/progress": "^2.0.3", - "@types/readline-sync": "^1.4.3", - "@types/rimraf": "^3.0.2", - "@types/stack-trace": "^0.0.29", - "@types/yargs": "13.0.4", - "@zowe/secrets-for-zowe-sdk": "^7.18.0", - "chalk": "2.4.2", - "cli-table3": "0.6.2", - "comment-json": "4.1.1", - "concurrently": "^7.5.0", - "cowsay": "^1.2.1", - "cross-spawn": "7.0.3", - "dataobject-parser": "1.2.25", - "deep-diff": "^0.3.8", - "deepmerge": "4.2.2", - "diff": "5.1.0", - "diff2html": "3.4.20-usewontache.1.60e7a2e", - "fast-glob": "3.2.7", - "fastest-levenshtein": "1.0.12", - "find-up": "4.1.0", - "fs-extra": "9.1.0", - "get-function-arguments": "^1.0.0", - "http-proxy-agent": "7.0.2", - "http-server": "^14.1.1", - "https-proxy-agent": "7.0.4", - "jest-diff": "27.0.6", - "js-yaml": "4.1.0", - "jsonfile": "6.1.0", - "jsonschema": "1.4.1", - "lodash": "4.17.21", - "lodash-deep": "2.0.0", - "log4js": "6.4.6", - "markdown-it": "14.1.0", - "mustache": "4.2.0", - "npm-package-arg": "9.1.0", - "opener": "1.5.2", - "pacote": "17.0.6", - "prettyjson": "1.2.2", - "progress": "2.0.3", - "read": "1.0.7", - "readline-sync": "1.4.10", - "semver": "7.5.4", - "stack-trace": "0.0.10", - "stream-to-string": "^1.2.0", - "strip-ansi": "6.0.1", - "tsc-watch": "^5.0.3", - "uuid": "^3.3.2", - "web-help": "file:web-help", - "which": "4.0.0", - "wrap-ansi": "7.0.0", - "yamljs": "0.3.0", - "yargs": "15.3.1", - "yargs-parser": "^18.1.2" - }, - "dependencies": { - "agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "requires": { - "debug": "^4.3.4" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "requires": { - "semver": "^7.0.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "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==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "diff2html": { - "version": "3.4.20-usewontache.1.60e7a2e", - "resolved": "https://registry.npmjs.org/diff2html/-/diff2html-3.4.20-usewontache.1.60e7a2e.tgz", - "integrity": "sha512-0ge1jQpRv9Eg6USdIgnDIzAnuhhlgFPmhglCUBNhSVU772biWWbSu/palu0uK+PbgidjkjkajztZGVAZnD56pw==", - "requires": { - "diff": "5.1.0", - "highlight.js": "11.6.0", - "wontache": "0.1.0" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "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==" - }, - "highlight.js": { - "version": "11.6.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.6.0.tgz", - "integrity": "sha512-ig1eqDzJaB0pqEvlPVIpSSyMaO92bH1N2rJpLMN/nX396wTpDA4Eq0uK+7I/2XG17pFaaKE0kjV/XPeGt7Evjw==", - "optional": true - }, - "hosted-git-info": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", - "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", - "requires": { - "lru-cache": "^7.5.1" - } - }, - "http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - }, - "isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==" - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "requires": { - "p-locate": "^4.1.0" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" - }, - "npm-package-arg": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.0.tgz", - "integrity": "sha512-4J0GL+u2Nh6OnhvUKXRr2ZMG4lR8qtLp+kv7UiV00Y+nGiSxtttCyIRHCt5L5BNkXQld/RceYItau3MDOoGiBw==", - "requires": { - "hosted-git-info": "^5.0.0", - "proc-log": "^2.0.1", - "semver": "^7.3.5", - "validate-npm-package-name": "^4.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "requires": { - "p-limit": "^2.2.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "validate-npm-package-name": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz", - "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", - "requires": { - "builtins": "^5.0.0" - } - }, - "which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", - "requires": { - "isexe": "^3.1.1" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "@zowe/provisioning-for-zowe-sdk": { - "version": "file:packages/provisioning", - "requires": { - "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1", - "js-yaml": "4.1.0" - } - }, - "@zowe/secrets-for-zowe-sdk": { - "version": "file:packages/secrets", - "requires": { - "@napi-rs/cli": "^2.16.2", - "ava": "^4.3.3" - } - }, - "@zowe/zos-console-for-zowe-sdk": { - "version": "file:packages/zosconsole", - "requires": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" - } - }, - "@zowe/zos-files-for-zowe-sdk": { - "version": "file:packages/zosfiles", - "requires": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1", - "@zowe/zos-uss-for-zowe-sdk": "7.29.2", - "minimatch": "5.0.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "@zowe/zos-jobs-for-zowe-sdk": { - "version": "file:packages/zosjobs", - "requires": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1", - "@zowe/zos-files-for-zowe-sdk": "7.29.2" - } - }, - "@zowe/zos-logs-for-zowe-sdk": { - "version": "file:packages/zoslogs", - "requires": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" - } - }, - "@zowe/zos-tso-for-zowe-sdk": { - "version": "file:packages/zostso", - "requires": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1", - "@zowe/zosmf-for-zowe-sdk": "7.29.2" - } - }, - "@zowe/zos-uss-for-zowe-sdk": { - "version": "file:packages/zosuss", - "requires": { - "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "7.29.2", - "@zowe/imperative": "5.27.1", - "ssh2": "1.15.0" - } - }, - "@zowe/zos-workflows-for-zowe-sdk": { - "version": "file:packages/workflows", - "requires": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1", - "@zowe/zos-files-for-zowe-sdk": "7.29.2" - } - }, - "@zowe/zosmf-for-zowe-sdk": { - "version": "file:packages/zosmf", - "requires": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" - } - }, - "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 - }, - "acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true - }, - "add-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", - "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "agentkeepalive": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", - "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "depd": "^1.1.2", - "humanize-ms": "^1.2.1" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "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 - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - }, - "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - } - } - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-parser": { - "version": "3.2.10", - "resolved": "https://registry.npmjs.org/ansi-parser/-/ansi-parser-3.2.10.tgz", - "integrity": "sha512-CGKGIbd678lm15IXJXI1cTyOVAnMQw0jES+klW/yIc+GzYccsYanLMhczPIIj2hE64B79g75QfiuWrEWd6nJdg==", - "dev": true - }, - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "app-module-path": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz", - "integrity": "sha1-ZBqlXft9am8KgUHEucCqULbCTdU=", - "dev": true - }, - "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true - }, - "are-we-there-yet": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-4.0.2.tgz", - "integrity": "sha512-ncSWAawFhKMJDTdoAeOV+jyW1VCMj5QIAwULIBV0SSR7B/RLPPEQiknKcg/RIIZlUQrxELpsxMiTUoAQ4sIUyg==", - "dev": true - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "optional": true, - "peer": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", - "dev": true - }, - "array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", - "dev": true - }, - "array-timsort": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", - "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==" - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "arrgv": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arrgv/-/arrgv-1.0.2.tgz", - "integrity": "sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true - }, - "asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "ast-module-types": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/ast-module-types/-/ast-module-types-2.7.1.tgz", - "integrity": "sha512-Rnnx/4Dus6fn7fTqdeLEAn5vUll5w7/vts0RN608yFa6si/rDOUonlIIiwugHBFWjylHjxm9owoSZn71KwG4gw==", - "dev": true - }, - "async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" - }, - "ava": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/ava/-/ava-4.3.3.tgz", - "integrity": "sha512-9Egq/d9R74ExrWohHeqUlexjDbgZJX5jA1Wq4KCTqc3wIfpGEK79zVy4rBtofJ9YKIxs4PzhJ8BgbW5PlAYe6w==", - "dev": true, - "requires": { - "acorn": "^8.7.1", - "acorn-walk": "^8.2.0", - "ansi-styles": "^6.1.0", - "arrgv": "^1.0.2", - "arrify": "^3.0.0", - "callsites": "^4.0.0", - "cbor": "^8.1.0", - "chalk": "^5.0.1", - "chokidar": "^3.5.3", - "chunkd": "^2.0.1", - "ci-info": "^3.3.1", - "ci-parallel-vars": "^1.0.1", - "clean-yaml-object": "^0.1.0", - "cli-truncate": "^3.1.0", - "code-excerpt": "^4.0.0", - "common-path-prefix": "^3.0.0", - "concordance": "^5.0.4", - "currently-unhandled": "^0.4.1", - "debug": "^4.3.4", - "del": "^6.1.1", - "emittery": "^0.11.0", - "figures": "^4.0.1", - "globby": "^13.1.1", - "ignore-by-default": "^2.1.0", - "indent-string": "^5.0.0", - "is-error": "^2.2.2", - "is-plain-object": "^5.0.0", - "is-promise": "^4.0.0", - "matcher": "^5.0.0", - "mem": "^9.0.2", - "ms": "^2.1.3", - "p-event": "^5.0.1", - "p-map": "^5.4.0", - "picomatch": "^2.3.1", - "pkg-conf": "^4.0.0", - "plur": "^5.1.0", - "pretty-ms": "^7.0.1", - "resolve-cwd": "^3.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.5", - "strip-ansi": "^7.0.1", - "supertap": "^3.0.1", - "temp-dir": "^2.0.0", - "write-file-atomic": "^4.0.1", - "yargs": "^17.5.1" - }, - "dependencies": { - "aggregate-error": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", - "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", - "dev": true, - "requires": { - "clean-stack": "^4.0.0", - "indent-string": "^5.0.0" - } - }, - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "arrify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-3.0.0.tgz", - "integrity": "sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==", - "dev": true - }, - "callsites": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-4.0.0.tgz", - "integrity": "sha512-y3jRROutgpKdz5vzEhWM34TidDU8vkJppF8dszITeb1PQmSqV3DTxyV8G/lyO/DNvtE1YTedehmw9MPZsCBHxQ==", - "dev": true - }, - "chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true - }, - "clean-stack": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", - "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", - "dev": true, - "requires": { - "escape-string-regexp": "5.0.0" - } - }, - "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, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "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 - }, - "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, - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, - "emittery": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.11.0.tgz", - "integrity": "sha512-S/7tzL6v5i+4iJd627Nhv9cLFIo5weAIlGccqJFpnBoDB8U1TF2k5tez4J/QNuxyyhWuFqHg1L84Kd3m7iXg6g==", - "dev": true - }, - "escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true - }, - "fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "figures": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/figures/-/figures-4.0.1.tgz", - "integrity": "sha512-rElJwkA/xS04Vfg+CaZodpso7VqBknOYbzi6I76hI4X80RUjkSxO2oAyPmGbuXUppywjqndOrQDl817hDnI++w==", - "dev": true, - "requires": { - "escape-string-regexp": "^5.0.0", - "is-unicode-supported": "^1.2.0" - } - }, - "globby": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", - "dev": true, - "requires": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", - "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, - "dependencies": { - "slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true - } - } - }, - "indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true - }, - "is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", - "dev": true - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "p-map": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-5.5.0.tgz", - "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", - "dev": true, - "requires": { - "aggregate-error": "^4.0.0" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "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" - } - }, - "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 - } - } - }, - "babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, - "requires": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "dependencies": { - "@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - } - }, - "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 - }, - "jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "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, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - } - }, - "babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "requires": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - } - }, - "babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "balloon-css": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/balloon-css/-/balloon-css-1.2.0.tgz", - "integrity": "sha512-urXwkHgwp6GsXVF+it01485Z2Cj4pnW02ICnM0TemOlkKmCNnDLmyy+ZZiRXBpwldUXO+aRNr7Hdia4CBvXJ5A==", - "dev": true - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true - }, - "basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.2" - } - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true - }, - "better-path-resolve": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz", - "integrity": "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==", - "dev": true, - "requires": { - "is-windows": "^1.0.0" - } - }, - "bin-links": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-3.0.3.tgz", - "integrity": "sha512-zKdnMPWEdh4F5INR07/eBrodC7QrF5JKvqskjz/ZZRXg5YSAZIbn8zGhbhUrElzHBZ2fvEQdOU59RHcTG3GiwA==", - "dev": true, - "requires": { - "cmd-shim": "^5.0.0", - "mkdirp-infer-owner": "^2.0.0", - "npm-normalize-package-bin": "^2.0.0", - "read-cmd-shim": "^3.0.0", - "rimraf": "^3.0.0", - "write-file-atomic": "^4.0.0" - }, - "dependencies": { - "npm-normalize-package-bin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", - "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "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==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "blueimp-md5": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", - "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", - "dev": true - }, - "bootstrap": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", - "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", - "dev": true, - "requires": {} - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "requires": { - "fill-range": "^7.1.1" - } - }, - "browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - } - }, - "bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "requires": { - "fast-json-stable-stringify": "2.x" - } - }, - "bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "requires": { - "node-int64": "^0.4.0" - } - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "buildcheck": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz", - "integrity": "sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==", - "optional": true - }, - "cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dev": true, - "requires": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "dependencies": { - "@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "dev": true, - "requires": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - } - }, - "@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - } - }, - "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, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "lru-cache": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz", - "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==", - "dev": true - }, - "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "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, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "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" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dev": true, - "requires": { - "unique-slug": "^3.0.0" - } - }, - "unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - } - } - }, - "call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - }, - "caniuse-lite": { - "version": "1.0.30001594", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001594.tgz", - "integrity": "sha512-VblSX6nYqyJVs8DKFMldE2IVCJjZ225LW00ydtUWwh5hk9IfkTOffO6r8gJNsH0qqqeAF8KrbMYA2VEwTlGW5g==", - "dev": true - }, - "cbor": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", - "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", - "dev": true, - "requires": { - "nofilter": "^3.1.0" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "chart.js": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.3.tgz", - "integrity": "sha512-qK1gkGSRYcJzqrrzdR6a+I0vQ4/R+SoODXyAjscQ/4mzuNzySaMCd+hyVxitSY1+L2fjPD1Gbn+ibNqRmwQeLw==", - "dev": true, - "requires": { - "@kurkle/color": "^0.3.0" - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.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" - } - }, - "chunkd": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chunkd/-/chunkd-2.0.1.tgz", - "integrity": "sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==", - "dev": true - }, - "ci-info": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", - "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", - "dev": true - }, - "ci-parallel-vars": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ci-parallel-vars/-/ci-parallel-vars-1.0.1.tgz", - "integrity": "sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==", - "dev": true - }, - "cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" - }, - "clean-yaml-object": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz", - "integrity": "sha512-3yONmlN9CSAkzNwnRCiJQ7Q2xK5mWuEfL3PuTZcAUzhObbXsfsnMptJzXwz93nc5zn9V9TwCVMmV7w4xsm43dw==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", - "dev": true - }, - "cli-table3": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz", - "integrity": "sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==", - "requires": { - "@colors/colors": "1.5.0", - "string-width": "^4.2.0" - } - }, - "cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", - "dev": true, - "requires": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "clipboard": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", - "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", - "dev": true, - "requires": { - "good-listener": "^1.2.2", - "select": "^1.1.2", - "tiny-emitter": "^2.0.0" - } - }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - } - } - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } - } - }, - "cmd-shim": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-5.0.0.tgz", - "integrity": "sha512-qkCtZ59BidfEwHltnJwkyVZn+XQojdAySM1D1gSeh11Z4pW1Kpolkyo53L5noc0nrxmIvyFwTmJRo4xs7FFLPw==", - "dev": true, - "requires": { - "mkdirp-infer-owner": "^2.0.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true - }, - "code-excerpt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", - "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", - "dev": true, - "requires": { - "convert-to-spaces": "^2.0.1" - } - }, - "collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, - "columnify": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", - "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", - "dev": true, - "requires": { - "strip-ansi": "^6.0.1", - "wcwidth": "^1.0.0" - } - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" - }, - "comment-json": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.1.1.tgz", - "integrity": "sha512-v8gmtPvxhBlhdRBLwdHSjGy9BgA23t9H1FctdQKyUrErPjSrJcdDMqBq9B4Irtm7w3TNYLQJNH6ARKnpyag1sA==", - "requires": { - "array-timsort": "^1.0.3", - "core-util-is": "^1.0.2", - "esprima": "^4.0.1", - "has-own-prop": "^2.0.0", - "repeat-string": "^1.6.1" - } - }, - "common-ancestor-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", - "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==", - "dev": true - }, - "common-path-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dev": true, - "requires": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - }, - "dependencies": { - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "requires": { - "is-obj": "^2.0.0" - } - }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - } - } - }, - "compute-scroll-into-view": { - "version": "1.0.20", - "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz", - "integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "concordance": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz", - "integrity": "sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==", - "dev": true, - "requires": { - "date-time": "^3.1.0", - "esutils": "^2.0.3", - "fast-diff": "^1.2.0", - "js-string-escape": "^1.0.1", - "lodash": "^4.17.15", - "md5-hex": "^3.0.1", - "semver": "^7.3.2", - "well-known-symbols": "^2.0.0" - } - }, - "concurrently": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.6.0.tgz", - "integrity": "sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "date-fns": "^2.29.1", - "lodash": "^4.17.21", - "rxjs": "^7.0.0", - "shell-quote": "^1.7.3", - "spawn-command": "^0.0.2-1", - "supports-color": "^8.1.0", - "tree-kill": "^1.2.2", - "yargs": "^17.3.1" - }, - "dependencies": { - "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, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "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, - "requires": { - "has-flag": "^4.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "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" - } - }, - "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 - } - } - }, - "config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dev": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "convert-to-spaces": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", - "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", - "dev": true - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "corser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", - "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", - "dev": true - }, - "cowsay": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cowsay/-/cowsay-1.5.0.tgz", - "integrity": "sha512-8Ipzr54Z8zROr/62C8f0PdhQcDusS05gKTS87xxdji8VbWefWly0k8BwGK7+VqamOrkv3eGsCkPtvlHzrhWsCA==", - "dev": true, - "requires": { - "get-stdin": "8.0.0", - "string-width": "~2.1.1", - "strip-final-newline": "2.0.0", - "yargs": "15.4.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "dependencies": { - "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 - }, - "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 - }, - "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, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "cpu-features": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.9.tgz", - "integrity": "sha512-AKjgn2rP2yJyfbepsmLfiYcmtNn/2eUvocUyM/09yB0YDiz39HteK/5/T4Onf0pmdYDMgkBoGvRLvEguzyL7wQ==", - "optional": true, - "requires": { - "buildcheck": "~0.0.6", - "nan": "^2.17.0" - } - }, - "create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "optional": true, - "peer": true - }, - "jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - } - }, - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - }, - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - } - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - } - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "optional": true, - "peer": true - } - } - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "optional": true, - "peer": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "cuint": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", - "integrity": "sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==", - "dev": true - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, - "data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "dev": true - }, - "dataobject-parser": { - "version": "1.2.25", - "resolved": "https://registry.npmjs.org/dataobject-parser/-/dataobject-parser-1.2.25.tgz", - "integrity": "sha512-BmHeQBJsyWNKrBtwAzdZYrbnToPJb2zDfB4l/rwXp7bzMY596cGkrZ3qiIhuK+PeWopVKdKMp6nG/CtKKr8wHg==" - }, - "date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.21.0" - } - }, - "date-format": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.9.tgz", - "integrity": "sha512-+8J+BOUpSrlKLQLeF8xJJVTxS8QfRSuJgwxSVvslzgO3E6khbI0F5mMEPf5mTYhCCm4h99knYP6H3W9n3BQFrg==" - }, - "date-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/date-time/-/date-time-3.1.0.tgz", - "integrity": "sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==", - "dev": true, - "requires": { - "time-zone": "^1.0.0" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "debuglog": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", - "integrity": "sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==", - "dev": true - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "deep-diff": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz", - "integrity": "sha512-yVn6RZmHiGnxRKR9sJb3iVV2XTF1Ghh2DiWRZ3dMnGc43yUdWWF/kX6lQyk3+P84iprfWKU/8zFTrlkvtFm1ug==", - "dev": true - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" - }, - "deepmerge-ts": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-5.1.0.tgz", - "integrity": "sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw==", - "dev": true - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "^1.0.2" - }, - "dependencies": { - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - } - } - }, - "define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - } - }, - "del": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", - "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", - "dev": true, - "requires": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true - }, - "delegate": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", - "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", - "dev": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "dependency-tree": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/dependency-tree/-/dependency-tree-8.1.2.tgz", - "integrity": "sha512-c4CL1IKxkKng0oT5xrg4uNiiMVFqTGOXqHSFx7XEFdgSsp6nw3AGGruICppzJUrfad/r7GLqt26rmWU4h4j39A==", - "dev": true, - "requires": { - "commander": "^2.20.3", - "debug": "^4.3.1", - "filing-cabinet": "^3.0.1", - "precinct": "^8.0.0", - "typescript": "^3.9.7" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "precinct": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/precinct/-/precinct-8.3.1.tgz", - "integrity": "sha512-pVppfMWLp2wF68rwHqBIpPBYY8Kd12lDhk8LVQzOwqllifVR15qNFyod43YLyFpurKRZQKnE7E4pofAagDOm2Q==", - "dev": true, - "requires": { - "commander": "^2.20.3", - "debug": "^4.3.3", - "detective-amd": "^3.1.0", - "detective-cjs": "^3.1.1", - "detective-es6": "^2.2.1", - "detective-less": "^1.0.2", - "detective-postcss": "^4.0.0", - "detective-sass": "^3.0.1", - "detective-scss": "^2.0.1", - "detective-stylus": "^1.0.0", - "detective-typescript": "^7.0.0", - "module-definition": "^3.3.1", - "node-source-walk": "^4.2.0" - } - }, - "typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", - "dev": true - } - } - }, - "deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true - }, - "detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true - }, - "detective-amd": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detective-amd/-/detective-amd-3.1.0.tgz", - "integrity": "sha512-G7wGWT6f0VErjUkE2utCm7IUshT7nBh7aBBH2VBOiY9Dqy2DMens5iiOvYCuhstoIxRKLrnOvVAz4/EyPIAjnw==", - "dev": true, - "requires": { - "ast-module-types": "^2.7.0", - "escodegen": "^2.0.0", - "get-amd-module-type": "^3.0.0", - "node-source-walk": "^4.0.0" - } - }, - "detective-cjs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/detective-cjs/-/detective-cjs-3.1.1.tgz", - "integrity": "sha512-JQtNTBgFY6h8uT6pgph5QpV3IyxDv+z3qPk/FZRDT9TlFfm5dnRtpH39WtQEr1khqsUxVqXzKjZHpdoQvQbllg==", - "dev": true, - "requires": { - "ast-module-types": "^2.4.0", - "node-source-walk": "^4.0.0" - } - }, - "detective-es6": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/detective-es6/-/detective-es6-2.2.1.tgz", - "integrity": "sha512-22z7MblxkhsIQGuALeGwCKEfqNy4WmgDGmfJCwdXbfDkVYIiIDmY513hiIWBvX3kCmzvvWE7RR7kAYxs01wwKQ==", - "dev": true, - "requires": { - "node-source-walk": "^4.0.0" - } - }, - "detective-less": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/detective-less/-/detective-less-1.0.2.tgz", - "integrity": "sha512-Rps1xDkEEBSq3kLdsdnHZL1x2S4NGDcbrjmd4q+PykK5aJwDdP5MBgrJw1Xo+kyUHuv3JEzPqxr+Dj9ryeDRTA==", - "dev": true, - "requires": { - "debug": "^4.0.0", - "gonzales-pe": "^4.2.3", - "node-source-walk": "^4.0.0" - } - }, - "detective-postcss": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detective-postcss/-/detective-postcss-4.0.0.tgz", - "integrity": "sha512-Fwc/g9VcrowODIAeKRWZfVA/EufxYL7XfuqJQFroBKGikKX83d2G7NFw6kDlSYGG3LNQIyVa+eWv1mqre+v4+A==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "is-url": "^1.2.4", - "postcss": "^8.1.7", - "postcss-values-parser": "^2.0.1" - } - }, - "detective-sass": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/detective-sass/-/detective-sass-3.0.1.tgz", - "integrity": "sha512-oSbrBozRjJ+QFF4WJFbjPQKeakoaY1GiR380NPqwdbWYd5wfl5cLWv0l6LsJVqrgWfFN1bjFqSeo32Nxza8Lbw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "gonzales-pe": "^4.2.3", - "node-source-walk": "^4.0.0" - } - }, - "detective-scss": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detective-scss/-/detective-scss-2.0.1.tgz", - "integrity": "sha512-VveyXW4WQE04s05KlJ8K0bG34jtHQVgTc9InspqoQxvnelj/rdgSAy7i2DXAazyQNFKlWSWbS+Ro2DWKFOKTPQ==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "gonzales-pe": "^4.2.3", - "node-source-walk": "^4.0.0" - } - }, - "detective-stylus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detective-stylus/-/detective-stylus-1.0.0.tgz", - "integrity": "sha1-UK7n24uruZA4HwEMY/q7pbWOVM0=", - "dev": true - }, - "detective-typescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/detective-typescript/-/detective-typescript-7.0.0.tgz", - "integrity": "sha512-y/Ev98AleGvl43YKTNcA2Q+lyFmsmCfTTNWy4cjEJxoLkbobcXtRS0Kvx06daCgr2GdtlwLfNzL553BkktfJoA==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "^4.8.2", - "ast-module-types": "^2.7.1", - "node-source-walk": "^4.2.0", - "typescript": "^3.9.7" - }, - "dependencies": { - "typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", - "dev": true - } - } - }, - "dezalgo": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", - "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", - "dev": true, - "requires": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==" - }, - "diff-sequences": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.4.0.tgz", - "integrity": "sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww==" - }, - "diff2html": { - "version": "3.4.48", - "resolved": "https://registry.npmjs.org/diff2html/-/diff2html-3.4.48.tgz", - "integrity": "sha512-1lzNSg0G0VPKZPTyi4knzV2nAWTXBy/QaWCKzDto6iEIlcuOJEG0li4bElJfpHNz+pBqPu4AcC1i9ZCo9KMUOg==", - "dev": true, - "requires": { - "diff": "5.1.0", - "highlight.js": "11.9.0", - "hogan.js": "3.0.2" - } - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" - }, - "electron-to-chromium": { - "version": "1.4.692", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.692.tgz", - "integrity": "sha512-d5rZRka9n2Y3MkWRN74IoAsxR0HK3yaAt7T50e3iT9VZmCCQDT3geXUO5ZRMhDToa1pkCeQXuNo+0g+NfDOVPA==", - "dev": true - }, - "emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true - }, - "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==" - }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "optional": true, - "requires": { - "iconv-lite": "^0.6.2" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, - "enhanced-resolve": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz", - "integrity": "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" - }, - "env-cmd": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/env-cmd/-/env-cmd-10.1.0.tgz", - "integrity": "sha512-mMdWTT9XKN7yNth/6N6g2GuKuJTsKMDHlQFUDacb/heQRRWOTIZ42t1rMHnQu4jYxU1ajdTeJM+9eEETlqToMA==", - "dev": true, - "requires": { - "commander": "^4.0.0", - "cross-spawn": "^7.0.0" - }, - "dependencies": { - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true - } - } - }, - "env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" - }, - "err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.4" - } - }, - "es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "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 - }, - "escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "source-map": "~0.6.1" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "eslint": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.25.0.tgz", - "integrity": "sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.10.5", - "@humanwhocodes/module-importer": "^1.0.1", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", - "globby": "^11.1.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "dependencies": { - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - } - } - }, - "eslint-plugin-deprecation": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-deprecation/-/eslint-plugin-deprecation-2.0.0.tgz", - "integrity": "sha512-OAm9Ohzbj11/ZFyICyR5N6LbOIvQMp7ZU2zI7Ej0jIc8kiGUERXPNMfw2QqqHD1ZHtjMub3yPZILovYEYucgoQ==", - "dev": true, - "requires": { - "@typescript-eslint/utils": "^6.0.0", - "tslib": "^2.3.1", - "tsutils": "^3.21.0" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" - } - }, - "@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - } - }, - "@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" - } - }, - "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, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - } - } - }, - "eslint-plugin-jest": { - "version": "26.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.9.0.tgz", - "integrity": "sha512-TWJxWGp1J628gxh2KhaH1H1paEdgE2J61BBF1I59c6xWeL5+D1BzMxGDN/nXAfX+aSkR5u80K+XhskK6Gwq9ng==", - "dev": true, - "requires": { - "@typescript-eslint/utils": "^5.10.0" - } - }, - "eslint-plugin-unused-imports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz", - "integrity": "sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==", - "dev": true, - "requires": { - "eslint-rule-composer": "^0.3.0" - } - }, - "eslint-rule-composer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", - "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", - "dev": true - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - } - }, - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - }, - "espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", - "dev": true, - "requires": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - } - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", - "dev": true, - "requires": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - }, - "dependencies": { - "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", - "dev": true, - "requires": { - "through": "2" - } - } - } - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true - }, - "expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "dev": true, - "requires": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - }, - "dependencies": { - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } - } - }, - "exponential-backoff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", - "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==" - }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - } - }, - "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==" - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "requires": { - "reusify": "^1.0.4" - } - }, - "fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", - "dev": true, - "requires": { - "bser": "2.1.1" - } - }, - "fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "dev": true, - "requires": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - }, - "dependencies": { - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - } - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "filing-cabinet": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/filing-cabinet/-/filing-cabinet-3.1.0.tgz", - "integrity": "sha512-ZFutWTo14Z1xmog76UoQzDKEza1fSpqc+HvUN6K6GILrfhIn6NbR8fHQktltygF+wbt7PZ/EvfLK6yJnebd40A==", - "dev": true, - "requires": { - "app-module-path": "^2.2.0", - "commander": "^2.20.3", - "debug": "^4.3.3", - "enhanced-resolve": "^5.8.3", - "is-relative-path": "^1.0.2", - "module-definition": "^3.3.1", - "module-lookup-amd": "^7.0.1", - "resolve": "^1.21.0", - "resolve-dependency-path": "^2.0.0", - "sass-lookup": "^3.0.0", - "stylus-lookup": "^3.0.1", - "typescript": "^3.9.7" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", - "dev": true - } - } - }, - "fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-package-json": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/find-package-json/-/find-package-json-1.2.0.tgz", - "integrity": "sha512-+SOGcLGYDJHtyqHd87ysBhmaeQ95oWspDKnMXBrnQ9Eq4OkLNqejgoaD8xVWu6GPa0B6roa6KinCMEMcVeqONw==", - "dev": true - }, - "find-process": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.7.tgz", - "integrity": "sha512-/U4CYp1214Xrp3u3Fqr9yNynUrr5Le4y0SsJh2lMDDSbpwYSz3M2SMWQC+wqcx79cN8PQtHQIL8KnuY9M66fdg==", - "requires": { - "chalk": "^4.0.0", - "commander": "^5.1.0", - "debug": "^4.1.1" - } - }, - "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==", - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" - }, - "flatten": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", - "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", - "dev": true - }, - "follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "dev": true - }, - "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==", - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "dependencies": { - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" - } - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dev": true, - "requires": { - "fetch-blob": "^3.1.2" - } - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", - "dev": true - }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "dependencies": { - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - } - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-arguments": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/function-arguments/-/function-arguments-1.0.9.tgz", - "integrity": "sha512-1Q6pDUjG3uve/ecbHEFpKUUOiPJzg6MZQV51f8c5pqlw1V6KCePQiztzOpQpdR/jnVJPXL2Q02xX1vNV22xx2Q==", - "dev": true - }, - "function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" - }, - "gauge": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-5.0.1.tgz", - "integrity": "sha512-CmykPMJGuNan/3S4kZOpvvPYSNqSHANiWnh9XcMU2pSjtBfF0XzZ2p1bFAxTbnFxyBuPxQYHhzwaoOmUdqzvxQ==", - "dev": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^4.0.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "dependencies": { - "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 - } - } - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true - }, - "get-amd-module-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-amd-module-type/-/get-amd-module-type-3.0.0.tgz", - "integrity": "sha512-99Q7COuACPfVt18zH9N4VAMyb81S6TUgJm2NgV6ERtkh9VIkAaByZkW530wl3lLN5KTtSrK9jVLxYsoP5hQKsw==", - "dev": true, - "requires": { - "ast-module-types": "^2.3.2", - "node-source-walk": "^4.0.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "get-function-arguments": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-function-arguments/-/get-function-arguments-1.0.0.tgz", - "integrity": "sha512-YQjTJR9BBAmY3lZAy9C0MU1Bm2gE1CLu0KtiU1VpFC9rFNtxTDUnqz+Ut18H87TGiZxhdKzFr+xIadTlhoAjXA==", - "dev": true, - "requires": { - "function-arguments": "^1.0.0" - } - }, - "get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "requires": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - } - }, - "get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", - "dev": true - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true - }, - "get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", - "dev": true - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" - }, - "git-up": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz", - "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==", - "dev": true, - "requires": { - "is-ssh": "^1.4.0", - "parse-url": "^8.1.0" - } - }, - "github-markdown-css": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/github-markdown-css/-/github-markdown-css-5.6.1.tgz", - "integrity": "sha512-DItLFgHd+s7HQmk63YN4/TdvLeRqk1QP7pPKTTPrDTYoI5x7f/luJWSOZxesmuxBI2srHp8RDyoZd+9WF+WK8Q==", - "dev": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "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" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "requires": { - "is-glob": "^4.0.1" - } - }, - "globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "dependencies": { - "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - } - } - }, - "gonzales-pe": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz", - "integrity": "sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "good-listener": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", - "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", - "dev": true, - "requires": { - "delegate": "^3.1.2" - } - }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "graphviz": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/graphviz/-/graphviz-0.0.9.tgz", - "integrity": "sha512-SmoY2pOtcikmMCqCSy2NO1YsRfu9OO0wpTlOYW++giGjfX1a6gax/m1Fo8IdUd0/3H15cTOfR1SMKwohj4LKsg==", - "dev": true, - "requires": { - "temp": "~0.4.0" - } - }, - "handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dev": true, - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "has-own-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", - "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==" - }, - "has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "requires": { - "es-define-property": "^1.0.0" - } - }, - "has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, - "hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", - "dev": true, - "requires": { - "function-bind": "^1.1.2" - } - }, - "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 - }, - "highlight.js": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", - "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==", - "dev": true, - "optional": true - }, - "hogan.js": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz", - "integrity": "sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==", - "dev": true, - "requires": { - "mkdirp": "0.3.0", - "nopt": "1.0.10" - }, - "dependencies": { - "mkdirp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", - "integrity": "sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==", - "dev": true - } - } - }, - "holderjs": { - "version": "2.9.9", - "resolved": "https://registry.npmjs.org/holderjs/-/holderjs-2.9.9.tgz", - "integrity": "sha512-ceWPz1MrR3dxOoZXiom+G48+l1VPG3TcjBw9fq5iwCiZAMvYX8Aia13GOxT7DoV/AcSyTH7Vvr11ygjZP9qn4w==", - "dev": true - }, - "html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, - "requires": { - "whatwg-encoding": "^2.0.0" - } - }, - "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 - }, - "http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "dependencies": { - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true - } - } - }, - "http-server": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", - "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", - "dev": true, - "requires": { - "basic-auth": "^2.0.1", - "chalk": "^4.1.2", - "corser": "^2.0.1", - "he": "^1.2.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy": "^1.18.1", - "mime": "^1.6.0", - "minimist": "^1.2.6", - "opener": "^1.5.1", - "portfinder": "^1.0.28", - "secure-compare": "3.0.1", - "union": "~0.5.0", - "url-join": "^4.0.1" - }, - "dependencies": { - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - } - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", - "dev": true, - "requires": { - "ms": "^2.0.0" - } - }, - "husky": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/husky/-/husky-6.0.0.tgz", - "integrity": "sha512-SQS2gDTB7tBN486QSoKPKQItZw97BMOd+Kdb6ghfpBc0yXyzrddI0oDV5MkDAbuB4X2mO3/nj60TRMcYxwzZeQ==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - }, - "ignore-by-default": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-2.1.0.tgz", - "integrity": "sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw==", - "dev": true - }, - "ignore-walk": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.4.tgz", - "integrity": "sha512-t7sv42WkwFkyKbivUCglsQW5YWMskWtbEf4MNKX5u/CCWHKSPzN4FtBQGsQZgCLbxOzpVlcbWVK5KB3auIOjSw==", - "requires": { - "minimatch": "^9.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" - }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "requires": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "dependencies": { - "sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" - } - } - }, - "irregular-plurals": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.5.0.tgz", - "integrity": "sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "requires": { - "has": "^1.0.3" - } - }, - "is-error": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-error/-/is-error-2.2.2.tgz", - "integrity": "sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "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==" - }, - "is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true - }, - "is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=" - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true - }, - "is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "dev": true - }, - "is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", - "dev": true - }, - "is-relative-path": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-relative-path/-/is-relative-path-1.0.2.tgz", - "integrity": "sha1-CRtGoNZ8HtD+hfH4z93gBrslHUY=", - "dev": true - }, - "is-ssh": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz", - "integrity": "sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==", - "dev": true, - "requires": { - "protocols": "^2.0.1" - } - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "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 - }, - "is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - } - }, - "istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "dev": true, - "requires": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - } - }, - "jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", - "dev": true, - "requires": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, - "dependencies": { - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } - } - }, - "jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", - "dev": true, - "requires": {} - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", - "dev": true, - "requires": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "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, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "optional": true, - "peer": true - }, - "jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - } - }, - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - }, - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - } - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "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" - } - }, - "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 - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "optional": true, - "peer": true - } - } - }, - "jest-diff": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.6.tgz", - "integrity": "sha512-Z1mqgkTCSYaFgwTlP/NUiRzdqgxmmhzHY1Tq17zL94morOHfHu3K4bgSgl+CR4GLhpV8VxkuOYuIWnQ9LnFqmg==", - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^27.0.6", - "jest-get-type": "^27.0.6", - "pretty-format": "^27.0.6" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" - }, - "jest-get-type": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.4.0.tgz", - "integrity": "sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ==" - }, - "pretty-format": { - "version": "27.4.6", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.4.6.tgz", - "integrity": "sha512-NblstegA1y/RJW2VyML+3LlpFjzx62cUrtBIKIWDXEDkjNeleA7Od7nrzcs/VLQvAeV4CgSYhrN39DRN88Qi/g==", - "requires": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - } - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - } - } - }, - "jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", - "dev": true, - "requires": { - "detect-newline": "^3.0.0" - } - }, - "jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "dependencies": { - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } - } - }, - "jest-environment-node-debug": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jest-environment-node-debug/-/jest-environment-node-debug-2.0.0.tgz", - "integrity": "sha1-XvCYlC/sG2r17khB9Pii/0GVYvk=", - "dev": true - }, - "jest-html-reporter": { - "version": "3.10.2", - "resolved": "https://registry.npmjs.org/jest-html-reporter/-/jest-html-reporter-3.10.2.tgz", - "integrity": "sha512-XRBa5ylHPUQoo8aJXEEdKsTruieTdlPbRktMx9WG9evMTxzJEKGFMaw5x+sQxJuClWdNR72GGwbOaz+6HIlksA==", - "dev": true, - "requires": { - "@jest/test-result": "^29.0.2", - "@jest/types": "^29.0.2", - "dateformat": "3.0.2", - "mkdirp": "^1.0.3", - "strip-ansi": "6.0.1", - "xmlbuilder": "15.0.0" - }, - "dependencies": { - "dateformat": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.2.tgz", - "integrity": "sha512-EelsCzH0gMC2YmXuMeaZ3c6md1sUJQxyb1XXc4xaisi/K6qKukqZhKPrEQyRkdNIncgYyLoDTReq0nNyuKerTg==", - "dev": true - } - } - }, - "jest-junit": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-12.3.0.tgz", - "integrity": "sha512-+NmE5ogsEjFppEl90GChrk7xgz8xzvF0f+ZT5AnhW6suJC93gvQtmQjfyjDnE0Z2nXJqEkxF0WXlvjG/J+wn/g==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "strip-ansi": "^5.2.0", - "uuid": "^8.3.2", - "xml": "^1.0.1" - }, - "dependencies": { - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", - "dev": true, - "requires": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true - }, - "jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - } - }, - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "dependencies": { - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } - } - }, - "jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true, - "requires": {} - }, - "jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - }, - "jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - } - }, - "jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true - }, - "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, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", - "dev": true, - "requires": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - }, - "dependencies": { - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - } - } - }, - "jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", - "dev": true, - "requires": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "dependencies": { - "@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - } - }, - "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 - }, - "jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "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, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "dependencies": { - "@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - } - }, - "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 - }, - "jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "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, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, - "dependencies": { - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "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 - }, - "diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true - }, - "jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - } - }, - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - }, - "jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "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, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-sonar-reporter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jest-sonar-reporter/-/jest-sonar-reporter-2.0.0.tgz", - "integrity": "sha512-ZervDCgEX5gdUbdtWsjdipLN3bKJwpxbvhkYNXTAYvAckCihobSLr9OT/IuyNIRT1EZMDDwR6DroWtrq+IL64w==", - "dev": true, - "requires": { - "xml": "^1.0.1" - } - }, - "jest-stare": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jest-stare/-/jest-stare-2.5.2.tgz", - "integrity": "sha512-dvxHXOsiJlvBi0n2dK9pz6RWFTdPB6njc2ZoMpyjmWI+aIL+X1W8OW5mTm1pkv/quy2ocKO/G+GsTe7Bv07xkQ==", - "dev": true, - "requires": { - "@jest/reporters": "^29.0.0", - "@jest/test-result": "^29.0.0", - "@jest/types": "^29.0.0", - "@types/jest": "^29.0.0", - "ansi-parser": "^3.2.10", - "bootstrap": "^5.0.0", - "chalk": "^4.1.0", - "chart.js": "^4.1.2", - "diff2html": "^3.4.40", - "holderjs": "^2.9.7", - "jquery": "^3.5.1", - "moment": "^2.27.0", - "mustache": "^4.0.0", - "pkg-up": "^3.0.0", - "popper.js": "^1.16.1", - "yargs": "^17.0.0" - }, - "dependencies": { - "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, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "17.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", - "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - }, - "yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==", - "dev": true - } - } - }, - "jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", - "dev": true, - "requires": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" - }, - "dependencies": { - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - } - } - }, - "jquery": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", - "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", - "dev": true - }, - "js-sdsl": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", - "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", - "dev": true - }, - "js-string-escape": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", - "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "requires": { - "argparse": "^2.0.1" - } - }, - "jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json-stringify-nice": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz", - "integrity": "sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" - }, - "jsonschema": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", - "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==" - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "jstree": { - "version": "3.3.16", - "resolved": "https://registry.npmjs.org/jstree/-/jstree-3.3.16.tgz", - "integrity": "sha512-yeeIJffi2WAqyMeHufXj/Ozy7GqgKdDkxfN8L8lwbG0h1cw/TgDafWmyhroH4AKgDSk9yW1W6jiJZu4zXAqzXw==", - "dev": true, - "requires": { - "jquery": "^3.5.0" - } - }, - "just-diff": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-5.1.1.tgz", - "integrity": "sha512-u8HXJ3HlNrTzY7zrYYKjNEfBlyjqhdBkoyTVdjtn7p02RJD5NvR8rIClzeGA7t+UYP1/7eAkWNLU0+P3QrEqKQ==", - "dev": true - }, - "just-diff-apply": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-5.4.1.tgz", - "integrity": "sha512-AAV5Jw7tsniWwih8Ly3fXxEZ06y+6p5TwQMsw0dzZ/wPKilzyDgdAnL0Ug4NNIquPUOh1vfFWEHbmXUqM5+o8g==", - "dev": true - }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "requires": { - "uc.micro": "^2.0.0" - } - }, - "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==", - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash-deep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lodash-deep/-/lodash-deep-2.0.0.tgz", - "integrity": "sha1-ypWPW82z1o0+w3rN8cWMHMvYhlw=", - "requires": { - "lodash": ">=3.7.0" - } - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "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, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "log4js": { - "version": "6.4.6", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.6.tgz", - "integrity": "sha512-1XMtRBZszmVZqPAOOWczH+Q94AI42mtNWjvjA5RduKTSWjEc56uOBbyM1CJnfN4Ym0wSd8cQ43zOojlSHgRDAw==", - "requires": { - "date-format": "^4.0.9", - "debug": "^4.3.4", - "flatted": "^3.2.5", - "rfdc": "^1.3.0", - "streamroller": "^3.0.8" - } - }, - "lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==" - }, - "lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true - }, - "madge": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/madge/-/madge-4.0.2.tgz", - "integrity": "sha512-l5bnA2dvyk0azLKDbOTCI+wDZ6nB007PhvPdmiYlPmqwVi49JPbhQrH/t4u8E6Akp3gwji1GZuA+v/F5q6yoWQ==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "commander": "^6.2.1", - "commondir": "^1.0.1", - "debug": "^4.0.1", - "dependency-tree": "^8.0.0", - "detective-amd": "^3.0.1", - "detective-cjs": "^3.1.1", - "detective-es6": "^2.1.0", - "detective-less": "^1.0.2", - "detective-postcss": "^4.0.0", - "detective-sass": "^3.0.1", - "detective-scss": "^2.0.1", - "detective-stylus": "^1.0.0", - "detective-typescript": "^7.0.0", - "graphviz": "0.0.9", - "ora": "^5.1.0", - "pluralize": "^8.0.0", - "precinct": "^7.0.0", - "pretty-ms": "^7.0.0", - "rc": "^1.2.7", - "typescript": "^3.9.5", - "walkdir": "^0.4.1" - }, - "dependencies": { - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true - }, - "typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", - "dev": true - } - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "requires": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz", - "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==", - "dev": true - }, - "minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "requires": { - "encoding": "^0.1.13", - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - } - } - } - }, - "makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "requires": { - "tmpl": "1.0.5" - } - }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==", - "dev": true - }, - "markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "requires": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - } - }, - "marked": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.1.tgz", - "integrity": "sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw==", - "dev": true - }, - "matcher": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-5.0.0.tgz", - "integrity": "sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==", - "dev": true, - "requires": { - "escape-string-regexp": "^5.0.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true - } - } - }, - "md5-hex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz", - "integrity": "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==", - "dev": true, - "requires": { - "blueimp-md5": "^2.10.0" - } - }, - "mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==" - }, - "mem": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/mem/-/mem-9.0.2.tgz", - "integrity": "sha512-F2t4YIv9XQUBHt6AOJ0y7lSmP1+cY7Fm1DRh9GClTGzKST7UWLMx6ly9WZdLH/G/ppM5RL4MlQfRT71ri9t19A==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.3", - "mimic-fn": "^4.0.0" - }, - "dependencies": { - "mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true - } - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" - }, - "micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "requires": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - } - }, - "mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", - "dev": true - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "minipass": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.5.tgz", - "integrity": "sha512-rQ/p+KfKBkeNwo04U15i+hOwoVBVmekmm/HcfTkTN2t9pbQKCMm4eN5gFeqgrrSp/kH/7BYYhTIHOxGqzbBPaA==", - "requires": { - "yallist": "^4.0.0" - }, - "dependencies": { - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-fetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", - "dev": true, - "requires": { - "encoding": "^0.1.12", - "minipass": "^3.1.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-json-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", - "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", - "requires": { - "jsonparse": "^1.3.1", - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "requires": { - "minipass": "^3.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "mkdirp-infer-owner": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz", - "integrity": "sha512-sdqtiFt3lkOaYvTXSRIUjkIdPTcxgv5+fgqYE/5qgwdw12cOrAuzzgzvVExIkH/ul1oeHN3bCLOWSG3XOqbKKw==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "infer-owner": "^1.0.4", - "mkdirp": "^1.0.3" - }, - "dependencies": { - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - } - } - }, - "module-definition": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/module-definition/-/module-definition-3.3.1.tgz", - "integrity": "sha512-kLidGPwQ2yq484nSD+D3JoJp4Etc0Ox9P0L34Pu/cU4X4HcG7k7p62XI5BBuvURWMRX3RPyuhOcBHbKus+UH4A==", - "dev": true, - "requires": { - "ast-module-types": "^2.7.1", - "node-source-walk": "^4.0.0" - } - }, - "module-lookup-amd": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/module-lookup-amd/-/module-lookup-amd-7.0.1.tgz", - "integrity": "sha512-w9mCNlj0S8qviuHzpakaLVc+/7q50jl9a/kmJ/n8bmXQZgDPkQHnPBb8MUOYh3WpAYkXuNc2c+khsozhIp/amQ==", - "dev": true, - "requires": { - "commander": "^2.8.1", - "debug": "^4.1.0", - "glob": "^7.1.6", - "requirejs": "^2.3.5", - "requirejs-config-file": "^4.0.0" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - } - } - }, - "moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==" - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" - }, - "nan": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", - "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", - "optional": true - }, - "nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "new-github-release-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/new-github-release-url/-/new-github-release-url-2.0.0.tgz", - "integrity": "sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==", - "dev": true, - "requires": { - "type-fest": "^2.5.1" - }, - "dependencies": { - "type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true - } - } - }, - "node-cleanup": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", - "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", - "dev": true - }, - "node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "dev": true - }, - "node-gyp": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.0.tgz", - "integrity": "sha512-A6rJWfXFz7TQNjpldJ915WFb1LnhO4lIve3ANPbWreuEoLoKlFT3sxIepPBkLhM27crW8YmN+pjlgbasH6cH/Q==", - "dev": true, - "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "dependencies": { - "are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "dev": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - } - }, - "nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "requires": { - "abbrev": "^1.0.0" - } - }, - "npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "dev": true, - "requires": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - } - }, - "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==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", - "dev": true - }, - "node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true - }, - "node-source-walk": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/node-source-walk/-/node-source-walk-4.2.0.tgz", - "integrity": "sha512-hPs/QMe6zS94f5+jG3kk9E7TNm4P2SulrKiLWMzKszBfNZvL/V6wseHlTd7IvfW0NZWqPtK3+9yYNr+3USGteA==", - "dev": true, - "requires": { - "@babel/parser": "^7.0.0" - } - }, - "nofilter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", - "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", - "dev": true - }, - "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "npm-bundled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", - "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", - "dev": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-install-checks": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", - "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", - "requires": { - "semver": "^7.1.1" - } - }, - "npm-lockfile": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/npm-lockfile/-/npm-lockfile-3.0.4.tgz", - "integrity": "sha512-IJQU7kkge0BESQDQByB+xOtAwI2Ni6UVlf019yI6VQ26A8sUthlNwnHtHyLbWfYwynoQiEOujwRemsA/hJPUXw==", - "dev": true, - "requires": { - "@npmcli/arborist": "=5.2.1", - "colors": "=1.4.0", - "find-package-json": "^1.2.0", - "object-inspect": "^1.12.2", - "yargs": "^17.5.1" - }, - "dependencies": { - "@npmcli/arborist": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-5.2.1.tgz", - "integrity": "sha512-DNyTHov3lU7PtCGHABzrPqQOUiBdiYzZ5dLv3D0RD5I9KbmhTLcZI/rv3ddZY0K9vpDE/R+R48b+cU/dUkL0Tw==", - "dev": true, - "requires": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/map-workspaces": "^2.0.3", - "@npmcli/metavuln-calculator": "^3.0.1", - "@npmcli/move-file": "^2.0.0", - "@npmcli/name-from-folder": "^1.0.1", - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/package-json": "^2.0.0", - "@npmcli/run-script": "^3.0.0", - "bin-links": "^3.0.0", - "cacache": "^16.0.6", - "common-ancestor-path": "^1.0.1", - "json-parse-even-better-errors": "^2.3.1", - "json-stringify-nice": "^1.1.4", - "mkdirp": "^1.0.4", - "mkdirp-infer-owner": "^2.0.0", - "nopt": "^5.0.0", - "npm-install-checks": "^5.0.0", - "npm-package-arg": "^9.0.0", - "npm-pick-manifest": "^7.0.0", - "npm-registry-fetch": "^13.0.0", - "npmlog": "^6.0.2", - "pacote": "^13.0.5", - "parse-conflict-json": "^2.0.1", - "proc-log": "^2.0.0", - "promise-all-reject-late": "^1.0.0", - "promise-call-limit": "^1.0.1", - "read-package-json-fast": "^2.0.2", - "readdir-scoped-modules": "^1.1.0", - "rimraf": "^3.0.2", - "semver": "^7.3.7", - "ssri": "^9.0.0", - "treeverse": "^2.0.0", - "walk-up-path": "^1.0.0" - } - }, - "@npmcli/git": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-3.0.2.tgz", - "integrity": "sha512-CAcd08y3DWBJqJDpfuVL0uijlq5oaXaOJEKHKc4wqrjd00gkvTZB+nFuLn+doOOKddaQS9JfqtNoFCO2LCvA3w==", - "dev": true, - "requires": { - "@npmcli/promise-spawn": "^3.0.0", - "lru-cache": "^7.4.4", - "mkdirp": "^1.0.4", - "npm-pick-manifest": "^7.0.0", - "proc-log": "^2.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^2.0.2" - } - }, - "@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - } - }, - "@npmcli/promise-spawn": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-3.0.0.tgz", - "integrity": "sha512-s9SgS+p3a9Eohe68cSI3fi+hpcZUmXq5P7w0kMlAsWVtR7XbK3ptkZqKT2cK1zLDObJ3sR+8P59sJE0w/KTL1g==", - "dev": true, - "requires": { - "infer-owner": "^1.0.4" - } - }, - "@npmcli/run-script": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-3.0.3.tgz", - "integrity": "sha512-ZXL6qgC5NjwfZJ2nET+ZSLEz/PJgJ/5CU90C2S66dZY4Jw73DasS4ZCXuy/KHWYP0imjJ4VtA+Gebb5BxxKp9Q==", - "dev": true, - "requires": { - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/promise-spawn": "^3.0.0", - "node-gyp": "^8.4.1", - "read-package-json-fast": "^2.0.3" - } - }, - "are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "requires": { - "semver": "^7.0.0" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "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, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "dev": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - } - }, - "hosted-git-info": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz", - "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==", - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "lru-cache": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz", - "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==", - "dev": true - }, - "node-gyp": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", - "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", - "dev": true, - "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^9.1.0", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "dependencies": { - "@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - } - }, - "cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "dev": true, - "requires": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "make-fetch-happen": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", - "dev": true, - "requires": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" - } - }, - "ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - } - } - }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "npm-install-checks": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-5.0.0.tgz", - "integrity": "sha512-65lUsMI8ztHCxFz5ckCEC44DRvEGdZX5usQFriauxHEwt7upv1FKaQEmAtU0YnOAdwuNWCmk64xYiQABNrEyLA==", - "dev": true, - "requires": { - "semver": "^7.1.1" - } - }, - "npm-package-arg": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", - "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", - "dev": true, - "requires": { - "hosted-git-info": "^5.0.0", - "proc-log": "^2.0.1", - "semver": "^7.3.5", - "validate-npm-package-name": "^4.0.0" - } - }, - "npm-registry-fetch": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-13.3.1.tgz", - "integrity": "sha512-eukJPi++DKRTjSBRcDZSDDsGqRK3ehbxfFUcgaRd0Yp6kRwOwh2WVn0r+8rMB4nnuzvAk6rQVzl6K5CkYOmnvw==", - "dev": true, - "requires": { - "make-fetch-happen": "^10.0.6", - "minipass": "^3.1.6", - "minipass-fetch": "^2.0.3", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.1.2", - "npm-package-arg": "^9.0.1", - "proc-log": "^2.0.0" - }, - "dependencies": { - "minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "requires": { - "encoding": "^0.1.13", - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - } - } - } - }, - "npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "dev": true, - "requires": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - } - }, - "pacote": { - "version": "13.6.2", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-13.6.2.tgz", - "integrity": "sha512-Gu8fU3GsvOPkak2CkbojR7vjs3k3P9cA6uazKTHdsdV0gpCEQq2opelnEv30KRQWgVzP5Vd/5umjcedma3MKtg==", - "dev": true, - "requires": { - "@npmcli/git": "^3.0.0", - "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/promise-spawn": "^3.0.0", - "@npmcli/run-script": "^4.1.0", - "cacache": "^16.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "infer-owner": "^1.0.4", - "minipass": "^3.1.6", - "mkdirp": "^1.0.4", - "npm-package-arg": "^9.0.0", - "npm-packlist": "^5.1.0", - "npm-pick-manifest": "^7.0.0", - "npm-registry-fetch": "^13.0.1", - "proc-log": "^2.0.0", - "promise-retry": "^2.0.1", - "read-package-json": "^5.0.0", - "read-package-json-fast": "^2.0.3", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11" - }, - "dependencies": { - "@npmcli/run-script": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-4.2.1.tgz", - "integrity": "sha512-7dqywvVudPSrRCW5nTHpHgeWnbBtz8cFkOuKrecm6ih+oO9ciydhWt6OF7HlqupRRmB8Q/gECVdB9LMfToJbRg==", - "dev": true, - "requires": { - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/promise-spawn": "^3.0.0", - "node-gyp": "^9.0.0", - "read-package-json-fast": "^2.0.3", - "which": "^2.0.2" - } - }, - "node-gyp": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.0.tgz", - "integrity": "sha512-A6rJWfXFz7TQNjpldJ915WFb1LnhO4lIve3ANPbWreuEoLoKlFT3sxIepPBkLhM27crW8YmN+pjlgbasH6cH/Q==", - "dev": true, - "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - } - }, - "nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "requires": { - "abbrev": "^1.0.0" - } - } - } - }, - "read-package-json-fast": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", - "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", - "dev": true, - "requires": { - "json-parse-even-better-errors": "^2.3.0", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "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==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "socks-proxy-agent": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", - "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", - "dev": true, - "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - } - }, - "validate-npm-package-name": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz", - "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", - "dev": true, - "requires": { - "builtins": "^5.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yargs": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", - "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", - "dev": true, - "requires": { - "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.0.0" - } - }, - "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 - } - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", - "dev": true - }, - "npm-packlist": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.3.tgz", - "integrity": "sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==", - "dev": true, - "requires": { - "glob": "^8.0.1", - "ignore-walk": "^5.0.1", - "npm-bundled": "^2.0.0", - "npm-normalize-package-bin": "^2.0.0" - }, - "dependencies": { - "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, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "ignore-walk": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz", - "integrity": "sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==", - "dev": true, - "requires": { - "minimatch": "^5.0.1" - } - }, - "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "npm-bundled": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-2.0.1.tgz", - "integrity": "sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==", - "dev": true, - "requires": { - "npm-normalize-package-bin": "^2.0.0" - } - }, - "npm-normalize-package-bin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", - "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", - "dev": true - } - } - }, - "npm-pick-manifest": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-7.0.2.tgz", - "integrity": "sha512-gk37SyRmlIjvTfcYl6RzDbSmS9Y4TOBXfsPnoYqTHARNgWbyDiCSMLUpmALDj4jjcTZpURiEfsSHJj9k7EV4Rw==", - "dev": true, - "requires": { - "npm-install-checks": "^5.0.0", - "npm-normalize-package-bin": "^2.0.0", - "npm-package-arg": "^9.0.0", - "semver": "^7.3.5" - }, - "dependencies": { - "builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "requires": { - "semver": "^7.0.0" - } - }, - "hosted-git-info": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz", - "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==", - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - } - }, - "lru-cache": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz", - "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==", - "dev": true - }, - "npm-install-checks": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-5.0.0.tgz", - "integrity": "sha512-65lUsMI8ztHCxFz5ckCEC44DRvEGdZX5usQFriauxHEwt7upv1FKaQEmAtU0YnOAdwuNWCmk64xYiQABNrEyLA==", - "dev": true, - "requires": { - "semver": "^7.1.1" - } - }, - "npm-normalize-package-bin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", - "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", - "dev": true - }, - "npm-package-arg": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", - "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", - "dev": true, - "requires": { - "hosted-git-info": "^5.0.0", - "proc-log": "^2.0.1", - "semver": "^7.3.5", - "validate-npm-package-name": "^4.0.0" - } - }, - "validate-npm-package-name": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz", - "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", - "dev": true, - "requires": { - "builtins": "^5.0.0" - } - } - } - }, - "npm-registry-fetch": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-16.1.0.tgz", - "integrity": "sha512-PQCELXKt8Azvxnt5Y85GseQDJJlglTFM9L9U9gkv2y4e9s0k3GVDdOx3YoB6gm2Do0hlkzC39iCGXby+Wve1Bw==", - "requires": { - "make-fetch-happen": "^13.0.0", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.1.2", - "npm-package-arg": "^11.0.0", - "proc-log": "^3.0.0" - }, - "dependencies": { - "@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", - "requires": { - "semver": "^7.3.5" - } - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "requires": { - "semver": "^7.0.0" - } - }, - "cacache": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", - "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", - "requires": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - } - }, - "fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "requires": { - "minipass": "^7.0.3" - } - }, - "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - } - }, - "hosted-git-info": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", - "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", - "requires": { - "lru-cache": "^10.0.1" - } - }, - "make-fetch-happen": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", - "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", - "requires": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" - }, - "minipass-collect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", - "requires": { - "minipass": "^7.0.3" - } - }, - "minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", - "requires": { - "encoding": "^0.1.13", - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - } - }, - "npm-package-arg": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", - "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", - "requires": { - "hosted-git-info": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - } - }, - "proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==" - }, - "ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", - "requires": { - "minipass": "^7.0.3" - } - }, - "unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", - "requires": { - "unique-slug": "^4.0.0" - } - }, - "unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", - "requires": { - "builtins": "^5.0.0" - } - } - } - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "npmlog": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-7.0.1.tgz", - "integrity": "sha512-uJ0YFk/mCQpLBt+bxN88AKd+gyqZvZDbtiNxk6Waqcj2aPRyfVx8ITawkyQynxUagInjdYT1+qj4NfA5KJJUxg==", - "dev": true, - "requires": { - "are-we-there-yet": "^4.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^5.0.0", - "set-blocking": "^2.0.0" - } - }, - "object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==" - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true - }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", - "dev": true - }, - "p-event": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-5.0.1.tgz", - "integrity": "sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==", - "dev": true, - "requires": { - "p-timeout": "^5.0.2" - }, - "dependencies": { - "p-timeout": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", - "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==", - "dev": true - } - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "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==", - "requires": { - "p-limit": "^3.0.2" - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" - }, - "pacote": { - "version": "17.0.6", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-17.0.6.tgz", - "integrity": "sha512-cJKrW21VRE8vVTRskJo78c/RCvwJCn1f4qgfxL4w77SOWrTCRcmfkYHlHtS0gqpgjv3zhXflRtgsrUCX5xwNnQ==", - "requires": { - "@npmcli/git": "^5.0.0", - "@npmcli/installed-package-contents": "^2.0.1", - "@npmcli/promise-spawn": "^7.0.0", - "@npmcli/run-script": "^7.0.0", - "cacache": "^18.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^7.0.2", - "npm-package-arg": "^11.0.0", - "npm-packlist": "^8.0.0", - "npm-pick-manifest": "^9.0.0", - "npm-registry-fetch": "^16.0.0", - "proc-log": "^3.0.0", - "promise-retry": "^2.0.1", - "read-package-json": "^7.0.0", - "read-package-json-fast": "^3.0.0", - "sigstore": "^2.2.0", - "ssri": "^10.0.0", - "tar": "^6.1.11" - }, - "dependencies": { - "@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", - "requires": { - "semver": "^7.3.5" - } - }, - "@npmcli/installed-package-contents": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", - "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", - "requires": { - "npm-bundled": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - } - }, - "@npmcli/node-gyp": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", - "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==" - }, - "@npmcli/package-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.0.0.tgz", - "integrity": "sha512-OI2zdYBLhQ7kpNPaJxiflofYIpkNLi+lnGdzqUOfRmCF3r2l1nadcjtCYMJKv/Utm/ZtlffaUuTiAktPHbc17g==", - "requires": { - "@npmcli/git": "^5.0.0", - "glob": "^10.2.2", - "hosted-git-info": "^7.0.0", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^6.0.0", - "proc-log": "^3.0.0", - "semver": "^7.5.3" - } - }, - "@npmcli/run-script": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-7.0.4.tgz", - "integrity": "sha512-9ApYM/3+rBt9V80aYg6tZfzj3UWdiYyCt7gJUD1VJKvWF5nwKDSICXbYIQbspFTq6TOpbsEtIC0LArB8d9PFmg==", - "requires": { - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/package-json": "^5.0.0", - "@npmcli/promise-spawn": "^7.0.0", - "node-gyp": "^10.0.0", - "which": "^4.0.0" - } - }, - "abbrev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==" - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "requires": { - "semver": "^7.0.0" - } - }, - "cacache": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", - "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", - "requires": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - } - }, - "fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "requires": { - "minipass": "^7.0.3" - } - }, - "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - } - }, - "hosted-git-info": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", - "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", - "requires": { - "lru-cache": "^10.0.1" - } - }, - "isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==" - }, - "json-parse-even-better-errors": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", - "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==" - }, - "make-fetch-happen": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", - "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", - "requires": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" - }, - "minipass-collect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", - "requires": { - "minipass": "^7.0.3" - } - }, - "minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", - "requires": { - "encoding": "^0.1.13", - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - } - }, - "node-gyp": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz", - "integrity": "sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==", - "requires": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^10.3.10", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^13.0.0", - "nopt": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^4.0.0" - } - }, - "nopt": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", - "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", - "requires": { - "abbrev": "^2.0.0" - } - }, - "normalize-package-data": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.0.tgz", - "integrity": "sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==", - "requires": { - "hosted-git-info": "^7.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - } - }, - "npm-bundled": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", - "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==", - "requires": { - "npm-normalize-package-bin": "^3.0.0" - } - }, - "npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==" - }, - "npm-package-arg": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", - "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", - "requires": { - "hosted-git-info": "^7.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - } - }, - "npm-packlist": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-8.0.2.tgz", - "integrity": "sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==", - "requires": { - "ignore-walk": "^6.0.4" - } - }, - "npm-pick-manifest": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.0.0.tgz", - "integrity": "sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg==", - "requires": { - "npm-install-checks": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "npm-package-arg": "^11.0.0", - "semver": "^7.3.5" - } - }, - "proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==" - }, - "read-package-json": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-7.0.0.tgz", - "integrity": "sha512-uL4Z10OKV4p6vbdvIXB+OzhInYtIozl/VxUBPgNkBuUi2DeRonnuspmaVAMcrkmfjKGNmRndyQAbE7/AmzGwFg==", - "requires": { - "glob": "^10.2.2", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0" - } - }, - "ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", - "requires": { - "minipass": "^7.0.3" - } - }, - "unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", - "requires": { - "unique-slug": "^4.0.0" - } - }, - "unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", - "requires": { - "builtins": "^5.0.0" - } - }, - "which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", - "requires": { - "isexe": "^3.1.1" - } - } - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - }, - "dependencies": { - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - } - } - }, - "parse-conflict-json": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-2.0.2.tgz", - "integrity": "sha512-jDbRGb00TAPFsKWCpZZOT93SxVP9nONOSgES3AevqRq/CHvavEBvKAjxX9p5Y5F0RZLxH9Ufd9+RwtCsa+lFDA==", - "dev": true, - "requires": { - "json-parse-even-better-errors": "^2.3.1", - "just-diff": "^5.0.1", - "just-diff-apply": "^5.2.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "parse-ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", - "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", - "dev": true - }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, - "parse-path": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz", - "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==", - "dev": true, - "requires": { - "protocols": "^2.0.0" - } - }, - "parse-url": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz", - "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==", - "dev": true, - "requires": { - "parse-path": "^7.0.0" - } - }, - "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==" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "requires": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "dependencies": { - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" - } - } - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", - "dev": true, - "requires": { - "through": "~2.3" - } - }, - "picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - }, - "pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true - }, - "pkg-conf": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-4.0.0.tgz", - "integrity": "sha512-7dmgi4UY4qk+4mj5Cd8v/GExPo0K+SlY+hulOSdfZ/T6jVH6//y7NtzZo5WrfhDBxuQ0jCa7fLZmNaNh7EWL/w==", - "dev": true, - "requires": { - "find-up": "^6.0.0", - "load-json-file": "^7.0.0" - }, - "dependencies": { - "find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, - "requires": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - } - }, - "load-json-file": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", - "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", - "dev": true - }, - "locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "requires": { - "p-locate": "^6.0.0" - } - }, - "p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "requires": { - "yocto-queue": "^1.0.0" - } - }, - "p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, - "requires": { - "p-limit": "^4.0.0" - } - }, - "path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true - }, - "yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", - "dev": true - } - } - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - } - } - }, - "plur": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/plur/-/plur-5.1.0.tgz", - "integrity": "sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==", - "dev": true, - "requires": { - "irregular-plurals": "^3.3.0" - } - }, - "pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "dev": true - }, - "popper.js": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", - "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", - "dev": true - }, - "portfinder": { - "version": "1.0.32", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", - "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", - "dev": true, - "requires": { - "async": "^2.6.4", - "debug": "^3.2.7", - "mkdirp": "^0.5.6" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - } - } - }, - "postcss": { - "version": "8.4.41", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", - "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", - "dev": true, - "requires": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" - } - }, - "postcss-url": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-10.1.3.tgz", - "integrity": "sha512-FUzyxfI5l2tKmXdYc6VTu3TWZsInayEKPbiyW+P6vmmIrrb4I6CGX0BFoewgYHLK+oIL5FECEK02REYRpBvUCw==", - "dev": true, - "requires": { - "make-dir": "~3.1.0", - "mime": "~2.5.2", - "minimatch": "~3.0.4", - "xxhashjs": "~0.2.2" - }, - "dependencies": { - "minimatch": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "postcss-values-parser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", - "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", - "dev": true, - "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "precinct": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/precinct/-/precinct-7.1.0.tgz", - "integrity": "sha512-I1RkW5PX51/q6Xl39//D7x9NgaKNGHpR5DCNaoxP/b2+KbzzXDNhauJUMV17KSYkJA41CSpwYUPRtRoNxbshWA==", - "dev": true, - "requires": { - "commander": "^2.20.3", - "debug": "^4.3.1", - "detective-amd": "^3.0.1", - "detective-cjs": "^3.1.1", - "detective-es6": "^2.2.0", - "detective-less": "^1.0.2", - "detective-postcss": "^4.0.0", - "detective-sass": "^3.0.1", - "detective-scss": "^2.0.1", - "detective-stylus": "^1.0.0", - "detective-typescript": "^6.0.0", - "module-definition": "^3.3.1", - "node-source-walk": "^4.2.0" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "detective-typescript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/detective-typescript/-/detective-typescript-6.0.0.tgz", - "integrity": "sha512-vTidcSDK3QostdbrH2Rwf9FhvrgJ4oIaVw5jbolgruTejexk6nNa9DShGpuS8CFVDb1IP86jct5BaZt1wSxpkA==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "^4.8.2", - "ast-module-types": "^2.7.1", - "node-source-walk": "^4.2.0", - "typescript": "^3.9.7" - } - }, - "typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", - "dev": true - } - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "pretty-ms": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", - "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==", - "dev": true, - "requires": { - "parse-ms": "^2.1.0" - } - }, - "prettyjson": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/prettyjson/-/prettyjson-1.2.2.tgz", - "integrity": "sha512-hDso231aQslRQPJjuSMIyUTN5CmW78AwEHlvigOs9E9IO+blW1AJTCJC6pQ8FArBSFsp5ZUdZsWXCUfXiD2D0w==", - "requires": { - "colors": "1.4.0", - "minimist": "^1.2.0" - } - }, - "proc-log": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz", - "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==" - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" - }, - "promise-all-reject-late": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz", - "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==", - "dev": true - }, - "promise-call-limit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-1.0.1.tgz", - "integrity": "sha512-3+hgaa19jzCGLuSCbieeRsu5C2joKfYn8pY6JAuXFRVfF4IO+L7UPpFWNTeWT9pM7uhskvbPPd/oEOktCn317Q==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" - }, - "promise-polyfill": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-1.1.6.tgz", - "integrity": "sha512-7rrONfyLkDEc7OJ5QBkqa4KI4EBhCd340xRuIUPGCfu13znS+vx+VDdrT9ODAJHlXm7w4lbxN3DRjyv58EuzDg==", - "dev": true - }, - "promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "requires": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - } - }, - "prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - } - }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "dev": true - }, - "protocols": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", - "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==", - "dev": true - }, - "ps-tree": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", - "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", - "dev": true, - "requires": { - "event-stream": "=3.3.4" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==" - }, - "pure-rand": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", - "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", - "dev": true - }, - "qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dev": true, - "requires": { - "side-channel": "^1.0.6" - } - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - } - } - }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "requires": { - "mute-stream": "~0.0.4" - } - }, - "read-cmd-shim": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-3.0.1.tgz", - "integrity": "sha512-kEmDUoYf/CDy8yZbLTmhB1X9kkjf9Q80PCNsDMb7ufrGd6zZSQA1+UyjrO+pZm5K/S4OXCWJeiIt1JA8kAsa6g==", - "dev": true - }, - "read-package-json": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-5.0.2.tgz", - "integrity": "sha512-BSzugrt4kQ/Z0krro8zhTwV1Kd79ue25IhNN/VtHFy1mG/6Tluyi+msc0UpwaoQzxSHa28mntAjIZY6kEgfR9Q==", - "dev": true, - "requires": { - "glob": "^8.0.1", - "json-parse-even-better-errors": "^2.3.1", - "normalize-package-data": "^4.0.0", - "npm-normalize-package-bin": "^2.0.0" - }, - "dependencies": { - "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, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "hosted-git-info": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz", - "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==", - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - } - }, - "lru-cache": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz", - "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==", - "dev": true - }, - "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "normalize-package-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", - "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", - "dev": true, - "requires": { - "hosted-git-info": "^5.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - } - }, - "npm-normalize-package-bin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", - "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", - "dev": true - } - } - }, - "read-package-json-fast": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", - "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", - "requires": { - "json-parse-even-better-errors": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "dependencies": { - "json-parse-even-better-errors": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", - "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==" - }, - "npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==" - } - } - }, - "readdir-scoped-modules": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", - "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", - "dev": true, - "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "readline-sync": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", - "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==" - }, - "regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", - "dev": true - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "rename-overwrite": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/rename-overwrite/-/rename-overwrite-4.0.3.tgz", - "integrity": "sha512-e1zOWZh4Lauz5DcLMC8j4eoOHPIrZkAVpiocE9SkDE1ZrGMW+W88LR1Y2YjD1DFgOYfJWqSsK6JKsRfuRH+tbQ==", - "dev": true, - "requires": { - "@zkochan/rimraf": "^2.1.2", - "fs-extra": "10.1.0" - }, - "dependencies": { - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - } - } - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" - }, - "requirejs": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.7.tgz", - "integrity": "sha512-DouTG8T1WanGok6Qjg2SXuCMzszOo0eHeH9hDZ5Y4x8Je+9JB38HdTLT4/VA8OaUhBa0JPVHJ0pyBkM1z+pDsw==", - "dev": true - }, - "requirejs-config-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/requirejs-config-file/-/requirejs-config-file-4.0.0.tgz", - "integrity": "sha512-jnIre8cbWOyvr8a5F2KuqBnY+SDA4NXr/hzEZJG79Mxm2WiFQz2dzhC8ibtPJS7zkmBEl1mxSwp5HhC1W4qpxw==", - "dev": true, - "requires": { - "esprima": "^4.0.0", - "stringify-object": "^3.2.1" - } - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - } - }, - "resolve-dependency-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-dependency-path/-/resolve-dependency-path-2.0.0.tgz", - "integrity": "sha512-DIgu+0Dv+6v2XwRaNWnumKu7GPufBBOr5I1gRPJHkvghrfCGOooJODFvgFimX/KRxk9j0whD2MnKHzM1jYvk9w==", - "dev": true - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==" - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" - }, - "rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "requires": { - "tslib": "^2.1.0" - }, - "dependencies": { - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true - } - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sass-lookup": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/sass-lookup/-/sass-lookup-3.0.0.tgz", - "integrity": "sha512-TTsus8CfFRn1N44bvdEai1no6PqdmDiQUiqW5DlpmtT+tYnIt1tXtDIph5KA1efC+LmioJXSnCtUVpcK9gaKIg==", - "dev": true, - "requires": { - "commander": "^2.16.0" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - } - } - }, - "scroll-into-view-if-needed": { - "version": "2.2.29", - "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz", - "integrity": "sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg==", - "dev": true, - "requires": { - "compute-scroll-into-view": "^1.0.17" - } - }, - "secure-compare": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", - "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", - "dev": true - }, - "select": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", - "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==", - "dev": true - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "requires": { - "type-fest": "^0.13.1" - }, - "dependencies": { - "type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true - } - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", - "dev": true, - "requires": { - "define-data-property": "^1.1.2", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" - } - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - }, - "dependencies": { - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } - } - }, - "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==", - "requires": { - "shebang-regex": "^3.0.0" - }, - "dependencies": { - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - } - } - }, - "shebang-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-2.0.0.tgz", - "integrity": "sha1-9QC/aFG2E1YjYWfeLMMZsP1/BoE=", - "dev": true - }, - "shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", - "dev": true - }, - "shiki": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.11.1.tgz", - "integrity": "sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==", - "dev": true, - "requires": { - "jsonc-parser": "^3.0.0", - "vscode-oniguruma": "^1.6.1", - "vscode-textmate": "^6.0.0" - } - }, - "side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "sigstore": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.2.2.tgz", - "integrity": "sha512-2A3WvXkQurhuMgORgT60r6pOWiCOO5LlEqY2ADxGBDGVYLSo5HN0uLtb68YpVpuL/Vi8mLTe7+0Dx2Fq8lLqEg==", - "requires": { - "@sigstore/bundle": "^2.2.0", - "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.0", - "@sigstore/sign": "^2.2.3", - "@sigstore/tuf": "^2.3.1", - "@sigstore/verify": "^1.1.0" - } - }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true - } - } - }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" - }, - "socks": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.3.tgz", - "integrity": "sha512-vfuYK48HXCTFD03G/1/zkIls3Ebr2YNa4qU9gHDZdblHLiqhJrJGkY3+0Nx0JpN9qBhJbVObc1CNciT1bIZJxw==", - "requires": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" - } - }, - "socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "dev": true - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", - "dev": true - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==" - }, - "split.js": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/split.js/-/split.js-1.6.5.tgz", - "integrity": "sha512-mPTnGCiS/RiuTNsVhCm9De9cCAUsrNFFviRbADdKiiV+Kk8HKp/0fWu7Kr8pi3/yBmsqLFHuXGT9UUZ+CNLwFw==", - "dev": true - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "ssh2": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.15.0.tgz", - "integrity": "sha512-C0PHgX4h6lBxYx7hcXwu3QWdh4tg6tZZsTfXcdvc5caW/EMxaB4H9dWsl7qk+F7LAW762hp8VbXOX7x4xUYvEw==", - "requires": { - "asn1": "^0.2.6", - "bcrypt-pbkdf": "^1.0.2", - "cpu-features": "~0.0.9", - "nan": "^2.18.0" - } - }, - "ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" - }, - "stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", - "dev": true, - "requires": { - "escape-string-regexp": "^2.0.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - } - } - }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", - "dev": true, - "requires": { - "duplexer": "~0.1.1" - } - }, - "stream-to-string": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/stream-to-string/-/stream-to-string-1.2.1.tgz", - "integrity": "sha512-WsvTDNF8UYs369Yko3pcdTducQtYpzEZeOV7cTuReyFvOoA9S/DLJ6sYK+xPafSPHhUMpaxiljKYnT6JSFztIA==", - "dev": true, - "requires": { - "promise-polyfill": "^1.1.6" - } - }, - "streamroller": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.8.tgz", - "integrity": "sha512-VI+ni3czbFZrd1MrlybxykWZ8sMDCMtTU7YJyhgb9M5X6d1DDxLdJr+gSnmRpXPMnIWxWKMaAE8K0WumBp3lDg==", - "requires": { - "date-format": "^4.0.9", - "debug": "^4.3.4", - "fs-extra": "^10.1.0" - }, - "dependencies": { - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-argv": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.1.2.tgz", - "integrity": "sha512-mBqPGEOMNJKXRo7z0keX0wlAhbBAjilUdPW13nN0PecVryZxdHIeM7TqbsSUA7VYuS00HGC6mojP7DlQzfa9ZA==", - "dev": true - }, - "string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "dev": true, - "requires": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - } - } - }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - } - } - }, - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "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 - }, - "strong-log-transformer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", - "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", - "dev": true, - "requires": { - "duplexer": "^0.1.1", - "minimist": "^1.2.0", - "through": "^2.3.4" - } - }, - "stylus-lookup": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/stylus-lookup/-/stylus-lookup-3.0.2.tgz", - "integrity": "sha512-oEQGHSjg/AMaWlKe7gqsnYzan8DLcGIHe0dUaFkucZZ14z4zjENRlQMCHT4FNsiWnJf17YN9OvrCfCoi7VvOyg==", - "dev": true, - "requires": { - "commander": "^2.8.1", - "debug": "^4.1.0" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - } - } - }, - "supertap": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/supertap/-/supertap-3.0.1.tgz", - "integrity": "sha512-u1ZpIBCawJnO+0QePsEiOknOfCRq0yERxiAchT0i4li0WHNUJbf0evXXSXOcCAR4M8iMDoajXYmstm/qO81Isw==", - "dev": true, - "requires": { - "indent-string": "^5.0.0", - "js-yaml": "^3.14.1", - "serialize-error": "^7.0.1", - "strip-ansi": "^7.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "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==", - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "symlink-dir": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/symlink-dir/-/symlink-dir-5.1.1.tgz", - "integrity": "sha512-kmVV2SfdoDksjJxStJ5N9u1ZZ5tQndCeUEG8St0tHI9BZe/ehZYbKB6eXPjo+AvFG1uRsDymUSGG0OLv2Ox8aQ==", - "dev": true, - "requires": { - "better-path-resolve": "^1.0.0", - "rename-overwrite": "^4.0.3" - } - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "temp": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.4.0.tgz", - "integrity": "sha1-ZxrWPVe+D+nXKUZks/xABjZnimA=", - "dev": true - }, - "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, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "time-zone": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", - "integrity": "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==", - "dev": true - }, - "tiny-emitter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", - "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - }, - "tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true - }, - "treeverse": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/treeverse/-/treeverse-2.0.0.tgz", - "integrity": "sha512-N5gJCkLu1aXccpOTtqV6ddSEi6ZmGkh3hjmbu1IjcavJK4qyOVQmi0myQKM7z5jVGmD68SJoliaVrMmVObhj6A==", - "dev": true - }, - "ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "requires": {} - }, - "ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", - "dev": true, - "requires": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" - }, - "dependencies": { - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "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 - } - } - }, - "ts-node": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", - "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", - "dev": true, - "requires": { - "arrify": "^1.0.0", - "buffer-from": "^1.1.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.6", - "yn": "^2.0.0" - }, - "dependencies": { - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - } - } - }, - "tsc-watch": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-5.0.3.tgz", - "integrity": "sha512-Hz2UawwELMSLOf0xHvAFc7anLeMw62cMVXr1flYmhRuOhOyOljwmb1l/O60ZwRyy1k7N1iC1mrn1QYM2zITfuw==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "node-cleanup": "^2.1.2", - "ps-tree": "^1.2.0", - "string-argv": "^0.1.1", - "strip-ansi": "^6.0.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "tuf-js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.0.tgz", - "integrity": "sha512-ZSDngmP1z6zw+FIkIBjvOp/II/mIub/O7Pp12j1WNsiCpg5R5wAc//i555bBQsE44O94btLt0xM/Zr2LQjwdCg==", - "requires": { - "@tufjs/models": "2.0.0", - "debug": "^4.3.4", - "make-fetch-happen": "^13.0.0" - }, - "dependencies": { - "@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", - "requires": { - "semver": "^7.3.5" - } - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "cacache": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", - "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", - "requires": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - } - }, - "fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "requires": { - "minipass": "^7.0.3" - } - }, - "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - } - }, - "make-fetch-happen": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", - "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", - "requires": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" - }, - "minipass-collect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", - "requires": { - "minipass": "^7.0.3" - } - }, - "minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", - "requires": { - "encoding": "^0.1.13", - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - } - }, - "ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", - "requires": { - "minipass": "^7.0.3" - } - }, - "unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", - "requires": { - "unique-slug": "^4.0.0" - } - }, - "unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", - "requires": { - "imurmurhash": "^0.1.4" - } - } - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "requires": { - "is-typedarray": "^1.0.0" - } - }, - "typedoc": { - "version": "0.23.17", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.17.tgz", - "integrity": "sha512-3rtNubo1dK0pvs6ixpMAq4pESULd5/JNUqJbdyZoeilI14reb1RNVomN4fMgIadd0RMX1aenYjJSSMBOJ+/+0Q==", - "dev": true, - "requires": { - "lunr": "^2.3.9", - "marked": "^4.0.19", - "minimatch": "^5.1.0", - "shiki": "^0.11.1" - }, - "dependencies": { - "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, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", - "dev": true - }, - "uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==" - }, - "uglify-js": { - "version": "3.17.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.3.tgz", - "integrity": "sha512-JmMFDME3iufZnBpyKL+uS78LRiC+mK55zWfM5f/pWBJfpOttXAqYfdDGRukYhJuyRinvPVAtUhvy7rlDybNtFg==", - "dev": true, - "optional": true - }, - "underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" - }, - "unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", - "dev": true - }, - "union": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", - "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", - "dev": true, - "requires": { - "qs": "^6.4.0" - } - }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", - "dev": true - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" - }, - "upath": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", - "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", - "dev": true - }, - "update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", - "dev": true - }, - "url-search-params-polyfill": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/url-search-params-polyfill/-/url-search-params-polyfill-8.2.5.tgz", - "integrity": "sha512-FOEojW4XReTmtZOB7xqSHmJZhrNTmClhBriwLTmle4iA7bwuCo6ldSfbtsFSb8bTf3E0a3XpfonAdaur9vqq8A==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "optional": true, - "peer": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "vscode-oniguruma": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", - "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==", - "dev": true - }, - "vscode-textmate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-6.0.0.tgz", - "integrity": "sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==", - "dev": true - }, - "walk-up-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-1.0.0.tgz", - "integrity": "sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg==", - "dev": true - }, - "walkdir": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.4.1.tgz", - "integrity": "sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ==", - "dev": true - }, - "walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "requires": { - "makeerror": "1.0.12" - } - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "web-help": { - "version": "file:packages/imperative/web-help", - "requires": { - "@types/jquery": "^3.5.30", - "@types/jstree": "^3.3.46", - "balloon-css": "^1.2.0", - "bootstrap": "^5.3.3", - "clipboard": "^2.0.11", - "github-markdown-css": "^5.6.1", - "jquery": "^3.7.1", - "jstree": "^3.3.16", - "postcss": "^8.4.41", - "postcss-url": "^10.1.3", - "scroll-into-view-if-needed": "2.2.29", - "split.js": "^1.6.5", - "url-search-params-polyfill": "^8.2.5" - } - }, - "web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "dev": true - }, - "well-known-symbols": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", - "integrity": "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==", - "dev": true - }, - "whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "dev": true, - "requires": { - "iconv-lite": "0.6.3" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "wontache": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/wontache/-/wontache-0.1.0.tgz", - "integrity": "sha512-UH4ikvEVRtvqY3DoW9/NjctB11FDuHjkKPO1tjaUVIVnZevxNtvba7lhR7H5TfMBVCpF2jwxH1qlu0UQSQ/zCw==", - "requires": { - "underscore": "^1.13.0-2" - } - }, - "word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - } - }, - "xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", - "dev": true - }, - "xmlbuilder": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.0.0.tgz", - "integrity": "sha512-KLu/G0DoWhkncQ9eHSI6s0/w+T4TM7rQaLhtCaL6tORv8jFlJPlnGumsgTcGfYeS1qZ/IHqrvDG7zJZ4d7e+nw==", - "dev": true - }, - "xxhashjs": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz", - "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==", - "dev": true, - "requires": { - "cuint": "^0.2.2" - } - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "yamljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", - "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", - "requires": { - "argparse": "^1.0.7", - "glob": "^7.0.5" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "~1.0.2" - } - } - } - }, - "yargs": { - "version": "15.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", - "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.1" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "requires": { - "p-limit": "^2.2.0" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ==", - "dev": true - }, - "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==" } } } diff --git a/package.json b/package.json index 5352d87e3d..2c707dc912 100644 --- a/package.json +++ b/package.json @@ -38,50 +38,47 @@ "typedoc:packages": "lerna run --parallel typedoc", "audit:public": "npm audit --registry https://registry.npmjs.org/", "bundle:webHelp": "cd packages/imperative/web-help && node build.js", - "prepare": "husky install && npm run bundle:webHelp", + "prepare": "husky && npm run bundle:webHelp", "package": "node scripts/bundleCliTgz.js" }, - "dependencies": {}, "devDependencies": { - "@lerna-lite/changed": "^3.3.0", - "@lerna-lite/cli": "^3.3.0", - "@lerna-lite/list": "^3.3.0", - "@lerna-lite/run": "^3.3.0", - "@lerna-lite/version": "^3.3.0", - "@types/jest": "^29.0.0", - "@types/node": "^14.18.28", - "@types/which": "^2.0.1", - "@typescript-eslint/eslint-plugin": "^5.33.0", - "@typescript-eslint/parser": "^5.33.0", - "ansi-colors": "^4.1.1", + "@lerna-lite/changed": "^3.6.0", + "@lerna-lite/cli": "^3.6.0", + "@lerna-lite/list": "^3.6.0", + "@lerna-lite/run": "^3.6.0", + "@lerna-lite/version": "^3.6.0", + "@types/jest": "^29.5.12", + "@types/node": "^18.19.17", + "@types/which": "^3.0.4", + "@typescript-eslint/eslint-plugin": "^7.15.0", + "@typescript-eslint/parser": "^7.15.0", + "ansi-colors": "^4.1.2", "chalk": "^4.1.0", "env-cmd": "^10.1.0", "eslint": "^8.22.0", - "eslint-plugin-deprecation": "^2.0.0", - "eslint-plugin-jest": "^26.8.0", - "eslint-plugin-unused-imports": "^2.0.0", - "fancy-log": "^1.3.3", - "glob": "^7.2.3", - "husky": "^6.0.0", + "eslint-plugin-deprecation": "^3.0.0", + "eslint-plugin-jest": "^27.0.0", + "eslint-plugin-unused-imports": "^3.0.0", + "fancy-log": "^2.0.0", + "husky": "^9.0.0", "jest": "^29.0.0", "jest-environment-node": "^29.0.0", "jest-environment-node-debug": "^2.0.0", "jest-html-reporter": "^3.6.0", - "jest-junit": "^12.0.0", + "jest-junit": "^16.0.0", "jest-sonar-reporter": "^2.0.0", - "jest-stare": "^2.2.0", + "jest-stare": "^2.5.1", "js-yaml": "^4.1.0", - "jsonfile": "^4.0.0", - "madge": "^4.0.1", + "jsonfile": "^6.0.0", + "madge": "^7.0.0", "mustache": "^4.2.0", - "npm-lockfile": "^3.0.4", - "rimraf": "^2.6.3", - "shebang-regex": "^2.0.0", - "symlink-dir": "^5.1.1", - "ts-jest": "^29.0.0", + "npm-lockfile": "^3.0.7", + "rimraf": "^5.0.0", + "symlink-dir": "^6.0.0", + "ts-jest": "^29.1.5", "ts-node": "^7.0.1", - "typedoc": "^0.23.10", - "typescript": "^4.0.0" + "typedoc": "^0.26.3", + "typescript": "^5.5.3" }, "jestSonar": { "reportPath": "__tests__/__results__/jest-sonar" diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 4274f87153..e92b9511f8 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -2,6 +2,159 @@ All notable changes to the Zowe CLI package will be documented in this file. +## Recent Changes + +- Update: Final prerelease + +## `8.0.0-next.202408261543` + +- BugFix: Updated `micromatch` dependency for technical currency. [#2242](https://github.com/zowe/zowe-cli/pull/2242) + +## `8.0.0-next.202408131445` + +- Update: See `7.28.3` for details + +## `8.0.0-next.202407181904` + +- Enhancement: The 'zowe config auto-init' command now generates a base profile name of 'global_base' or 'project_base', depending on whether a global or project configuration file is being generated. Related to Zowe Explorer issue https://github.com/zowe/zowe-explorer-vscode/issues/2682. + +## `8.0.0-next.202407021516` + +- BugFix: Updated dependencies for technical currency [#2188](https://github.com/zowe/zowe-cli/pull/2188) + +## `8.0.0-next.202406140245` + +- BugFix: Updated documentation for the `zos-files search ds` command's `--mainframe-search` option to include a disclaimer about z/OSMF API limitations. [#2160](https://github.com/zowe/zowe-cli/issues/2160) + +## `8.0.0-next.202406061600` + +- BugFix: Updated `braces` dependency for technical currency. [#2158](https://github.com/zowe/zowe-cli/pull/2158) + +## `8.0.0-next.202405231927` + +- LTS Breaking: Send all Zowe Daemon informational messages, progress messages, and error messages to standard error instead of standard output [#1451](https://github.com/zowe/zowe-cli/issues/1451) + +## `8.0.0-next.202405202020` + +- BugFix: Fixed a bug where a data set search would not return a search term if it was at the beginning of a line. [#2147](https://github.com/zowe/zowe-cli/pull/2147) + +## `8.0.0-next.202405101931` + +- Enhancement: Added the ability to search for a string in a data set or PDS member matching a pattern with the `zowe zos-files search data-sets` command.[#2095](https://github.com/zowe/zowe-cli/issues/2095) + +## `8.0.0-next.202405061946` + +- Enhancement: Consolidated the Zowe client log files into the same directory. [#2116](https://github.com/zowe/zowe-cli/issues/2116) + +## `8.0.0-next.202404301428` + +- LTS Breaking: Add informative messages identifying why a user is being prompted for connection property values during a CLI command. + +## `8.0.0-next.202404032038` + +- BugFix: Fixed error in `zos-files list all-members` command that could occur when members contain control characters in the name. [#2104](https://github.com/zowe/zowe-cli/pull/2104) + +## `8.0.0-next.202403272026` + +- BugFix: Resolved technical currency by updating `tar` dependency. [#2102](https://github.com/zowe/zowe-cli/issues/2102) +- BugFix: Resolved technical currency by updating `markdown-it` dependency. [#2107](https://github.com/zowe/zowe-cli/pull/2107) + +## `8.0.0-next.202403141949` + +- Enhancement: Changed references in command output from 'Team Configuration' to 'Zowe client configuration' [#2019](https://github.com/zowe/zowe-cli/issues/2019). + +## `8.0.0-next.202403132009` + +- Enhancement: Prompt for user/password on SSH commands when a token is stored in the config. [#2081](https://github.com/zowe/zowe-cli/pull/2081) + +## `8.0.0-next.202403131702` + +- BugFix: Removing stack trace for zosjobs errors. [#2078](https://github.com/zowe/zowe-cli/pull/2078) + +## `8.0.0-next.202403122137` + +- BugFix: Fixed default base profile missing in config generated by `zowe config auto-init` [#2088](https://github.com/zowe/zowe-cli/pull/2088) + +## `8.0.0-next.202403061549` + +- BugFix: Update daemon dependencies for technical currency [#2077](https://github.com/zowe/zowe-cli/pull/2077) + +## `8.0.0-next.202403041352` + +- BugFix: Updated engine to Node 18.12.0. [#2074](https://github.com/zowe/zowe-cli/pull/2074) +- BugFix: Eliminated a Node Version Manager (NVM) GUI popup dialog which NVM now displays during the `zowe config report-env` command by removing the NVM version number from our report. +- Enhancement: Replaced the term "Team configuration" with "Zowe client configuration" in the `zowe config report-env` command. + +## `8.0.0-next.202402261705` + +- BugFix: Updated additional dependencies for technical currency. [#2061](https://github.com/zowe/zowe-cli/pull/2061) +- BugFix: Updated engine to Node 16.7.0. [#2061](https://github.com/zowe/zowe-cli/pull/2061) + +## `8.0.0-next.202402211923` + +- Enhancement: Added new `zowe zos-jobs search job` command, which allows the user to search spool files for a specified string or regular expresion. +- BugFix: Updated dependencies for technical currency. [#2057](https://github.com/zowe/zowe-cli/pull/2057) + +## `8.0.0-next.202402132108` + +- LTS Breaking: Removed record format (recfm) validation when issuing `zowe files create` commands [#1699](https://github.com/zowe/zowe-cli/issues/1699) +- LTS Breaking: Added Zowe release version output for `--version` [#2028](https://github.com/zowe/zowe-cli/issues/2028) +- Enhancement: Added `name-only` alias to `root` on `config list` command [#1797](https://github.com/zowe/zowe-cli/issues/1797) +- BugFix: Resolved technical currency by updating `socks` transitive dependency + +## `8.0.0-next.202402021649` + +LTS Breaking: Removed the following previously deprecated items: [#1981](https://github.com/zowe/zowe-cli/pull/1981) + - Moved the many constants from `zowe-cli/packages/cli/src/Constants.ts` to `zowe-cli/packages/core/src/constants/Core.constants.ts` + - Removing `ZosFilesCreateExtraOptions.showAttributes` without replacement + - Moved all constants from `zowe-cli/packages/cli/src/zostso/constants/ZosTso.constants.ts` to `@zowe/zos-tso-for-zowe-sdk` + - Removed `isStderrEmptyForProfilesCommand` use `stripProfileDeprecationMessages` from `zowe-cli/__tests__/__packages__/cli-test-utils/src/TestUtils.ts` instead + - Removed `allDataSetsArchived`, `datasetsDownloadedSuccessfully`, `noDataSetsMatchingPatternRemain` and `onlyEmptyPartitionedDataSets` from ZosFiles.messages.ts + - Removed `getSpoolDownloadFile` use `getSpoolDownloadFilePath` instead + - Removed constants from ZosmfSession + - ZOSMF_OPTION_HOST_PROFILE use ZOSMF_OPTION_HOST instead + - ZOSMF_OPTION_USER_PROFILE use ZOSMF_OPTION_USER instead + - ZOSMF_OPTION_PASSWORD_PROFILE use ZOSMF_OPTION_PASSWORD instead + - Removed constants from SshSession.ts + - SSH_OPTION_USER_PROFILE use SSH_OPTION_USER + - SSH_OPTION_HOST_PROFILE use SSH_OPTION_HOST + - Removed zosmfProfile from `ZosFilesBase.handler.ts` + - Removed statCmdFlag as an export from Shell.ts + +## `8.0.0-next.202401262128` + +- Enhancement: Adding `--binary` and `--encoding` options to `zosfiles edit` + +## `8.0.0-next.202401191954` + +- LTS Breaking: Removed all 'profiles' commands, since they only worked with now-obsolete V1 profiles. +- BugFix: Properly construct workflow error messages to display properly with V3 error formatting. + +## `8.0.0-next.202401081937` + +- BugFix: Fixed typo in command help for `zowe zos-workflows create` commands. + +## `8.0.0-next.202401031939` + +- Enhancement: Revised help text for consistency [#1756](https://github.com/zowe/zowe-cli/issues/1756) + +## `8.0.0-next.202311291643` + +- LTS Breaking: Replaced the `ZOWE_EDITOR` environment variable with `ZOWE_OPT_EDITOR` and `--editor` option on commands [#1867](https://github.com/zowe/zowe-cli/issues/1867) + +## `8.0.0-next.202311282012` + +- LTS Breaking: Moved `getDataSet` from the `zosfiles` command group to the `zosfiles` SDK as `ZosFilesUtils.getDataSetFromName` [#1696](https://github.com/zowe/zowe-cli/issues/1696) + +## `8.0.0-next.202311141517` + +- LTS Breaking: Alter the format of error messages to be more clear and actionable. +- LTS Breaking: Remove the ```bright``` command from the product. + +## `8.0.0-next.202311132045` + +- Major: First major version bump for V3 + ## `7.29.1` - BugFix: Updated `micromatch` dependency for technical currency. [#2242](https://github.com/zowe/zowe-cli/pull/2242) diff --git a/packages/cli/__tests__/auth/__system__/__resources__/zowe.config_template.json b/packages/cli/__tests__/auth/__system__/__resources__/zowe.config_template.json new file mode 100644 index 0000000000..a0f8ca65d3 --- /dev/null +++ b/packages/cli/__tests__/auth/__system__/__resources__/zowe.config_template.json @@ -0,0 +1,46 @@ +{ + "$schema": "./zowe.schema.json", + "profiles": { + "zosmf": { + "type": "zosmf", + "properties": { + "port": 1443 + }, + "secure": [] + }, + "tso": { + "type": "tso", + "properties": { + "account": "", + "codePage": "1047", + "logonProcedure": "IZUFPROC" + }, + "secure": [] + }, + "ssh": { + "type": "ssh", + "properties": { + "port": 22 + }, + "secure": [] + }, + "base": { + "type": "base", + "properties": { + "host": "NoBaseHostVal", + "port": NoBasePortVal, + "rejectUnauthorized": NoBaseRejectUnauthVal, + "tokenType": "apimlAuthenticationToken" + }, + "secure": [ + "tokenValue" + ] + } + }, + "defaults": { + "zosmf": "zosmf", + "tso": "tso", + "ssh": "ssh", + "base": "base" + } +} \ No newline at end of file diff --git a/packages/cli/__tests__/auth/__system__/__scripts__/create_team_cfg.sh b/packages/cli/__tests__/auth/__system__/__scripts__/create_team_cfg.sh new file mode 100644 index 0000000000..d4dc8e2c4c --- /dev/null +++ b/packages/cli/__tests__/auth/__system__/__scripts__/create_team_cfg.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +HOST=${1:?"First parm (HOST) is required."} +PORT=${2:?"Second parm (PORT) is required."} +REJECT=${3:?"Third parm (REJECT) is required."} +scriptsDir=${4:?"Fourth parm (scriptsDir) is required."} + +# include exitOnFailure function +. "$scriptsDir/../../../../../../__tests__/__scripts__/exitOnFailure.sh" + +# copy our config file template +cp "$scriptsDir/../__resources__/zowe.config_template.json" . +exitOnFailure "Failed to copy config file." $? + +sed -e "s/NoBaseHostVal/$HOST/" \ + -e "s/NoBasePortVal/$PORT/" \ + -e "s/NoBaseRejectUnauthVal/$REJECT/" \ + < zowe.config_template.json > zowe.config.json +exitOnFailure "Failed to update config file." $? diff --git a/packages/cli/__tests__/auth/__system__/cli.auth.login.apiml.system.test.ts b/packages/cli/__tests__/auth/__system__/cli.auth.login.apiml.system.test.ts index f33f3cccb9..0c52a29e20 100644 --- a/packages/cli/__tests__/auth/__system__/cli.auth.login.apiml.system.test.ts +++ b/packages/cli/__tests__/auth/__system__/cli.auth.login.apiml.system.test.ts @@ -140,7 +140,11 @@ describe("auth login/logout apiml create profile", () => { await TestEnvironment.cleanUp(TEST_ENVIRONMENT_CREATE_PROF); }); - it("should successfully issue the login command and create a profile", () => { + /* Resurrect the following test after this Git issue is fixed: + https://github.com/zowe/zowe-cli/issues/2005 + */ + // eslint-disable-next-line jest/no-disabled-tests + it.skip("TODO: After 2005 is fixed: should successfully issue the login command and create a team config", () => { const response = runCliScript(__dirname + "/__scripts__/auth_login_apiml_create.sh", TEST_ENVIRONMENT_CREATE_PROF, [ @@ -152,18 +156,44 @@ describe("auth login/logout apiml create profile", () => { "y" ]); expect(response.stderr.toString()).toBe(""); - expect(response.status).toBe(0); expect(response.stdout.toString()).toContain("Login successful."); expect(response.stdout.toString()).toContain("The authentication token is stored in the"); // ${name} base profile + expect(response.status).toBe(0); }); - it("should successfully issue the logout command with a created profile", () => { - const response = runCliScript(__dirname + "/__scripts__/auth_logout_apiml.sh", - TEST_ENVIRONMENT_CREATE_PROF); + it("should successfully issue the logout command with a created team config", async () => { + // Form a posix-style path to scripts directory + let scriptsPosixPath = __dirname + "/__scripts__"; + scriptsPosixPath = scriptsPosixPath.replaceAll("\\", "/"); + scriptsPosixPath = scriptsPosixPath.replace(/^(.):(.*)/, "/$1$2"); + + // create a team config + let response = runCliScript(__dirname + "/__scripts__/create_team_cfg.sh", + TEST_ENVIRONMENT_CREATE_PROF, + [ + base.host, + base.port, + base.rejectUnauthorized, + scriptsPosixPath + ]); + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + + // login to create token in SCS + response = runCliScript(__dirname + "/__scripts__/auth_login_apiml.sh", TEST_ENVIRONMENT_CREATE_PROF, + [ + TEST_ENVIRONMENT_CREATE_PROF.systemTestProperties.base.user, + TEST_ENVIRONMENT_CREATE_PROF.systemTestProperties.base.password + ] + ); expect(response.stderr.toString()).toBe(""); expect(response.status).toBe(0); + + response = runCliScript(__dirname + "/__scripts__/auth_logout_apiml.sh", TEST_ENVIRONMENT_CREATE_PROF); + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("Logout successful. The authentication token has been revoked"); - expect(response.stdout.toString()).toContain("and removed from your 'default' base profile"); // V1 message + expect(response.stdout.toString()).toContain("Token was removed from your 'base' base profile"); // V1 message + expect(response.status).toBe(0); }); }); diff --git a/packages/cli/__tests__/config/auto-init/__integration__/__snapshots__/cli.config.auto-init.integration.test.ts.snap b/packages/cli/__tests__/config/auto-init/__integration__/__snapshots__/cli.config.auto-init.integration.test.ts.snap index c8d99c7f4c..95d595d34d 100644 --- a/packages/cli/__tests__/config/auto-init/__integration__/__snapshots__/cli.config.auto-init.integration.test.ts.snap +++ b/packages/cli/__tests__/config/auto-init/__integration__/__snapshots__/cli.config.auto-init.integration.test.ts.snap @@ -10,7 +10,7 @@ exports[`config auto-init help should display help 1`] = ` DESCRIPTION ----------- - Automatically generate a config from APIML + Automatically generate a config from APIML. USAGE ----- @@ -52,6 +52,15 @@ exports[`config auto-init help should display help 1`] = ` Default value: false + OPTIONS + ------- + + --editor | --ed (string) + + Editor that overrides the default editor for this file type. Set the option to + the editor's executable file location or the program's name: ie \\"--editor + notepad\\" + APIML CONNECTION OPTIONS ------------------------ @@ -126,8 +135,8 @@ exports[`config auto-init help should display help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: auto-init.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n auto-init\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Automatically generate a config from APIML\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe config auto-init [options]\\\\n\\\\n AUTOMATIC CONFIG INITIALIZATION OPTIONS\\\\n ---------------------------------------\\\\n\\\\n --user-config | --uc (boolean)\\\\n\\\\n Save config in the user layer\\\\n\\\\n Default value: false\\\\n\\\\n --global-config | --gc (boolean)\\\\n\\\\n Save config in the global layer\\\\n\\\\n Default value: false\\\\n\\\\n --dry-run | --dr | --dry (boolean)\\\\n\\\\n Display the outcome of the initialization without saving\\\\n\\\\n --edit | -e (boolean)\\\\n\\\\n Open in editor after initializing the configuration\\\\n\\\\n --overwrite | --ow (boolean)\\\\n\\\\n Replaces an existing configuration with a new configuration\\\\n\\\\n Default value: false\\\\n\\\\n --for-sure | -f (boolean)\\\\n\\\\n Confirms the overwrite option\\\\n\\\\n Default value: false\\\\n\\\\n APIML CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n Host name of the mainframe running the API Mediation Layer.\\\\n\\\\n --port | -P (number)\\\\n\\\\n Port number of API Mediation Layer on the mainframe.\\\\n\\\\n --user | -u (string)\\\\n\\\\n User name to authenticate to the API Mediation Layer on the mainframe.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Password to authenticate to the API Mediation Layer on the mainframe.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API Mediation Layer. Omit this option\\\\n to use the default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API Mediation Layer.\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use to authenticate to the API Mediation\\\\n Layer\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use to authenticate to the API\\\\n Mediation Layer\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n auto-init\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Automatically generate a config from APIML.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe config auto-init [options]\\\\n\\\\n AUTOMATIC CONFIG INITIALIZATION OPTIONS\\\\n ---------------------------------------\\\\n\\\\n --user-config | --uc (boolean)\\\\n\\\\n Save config in the user layer\\\\n\\\\n Default value: false\\\\n\\\\n --global-config | --gc (boolean)\\\\n\\\\n Save config in the global layer\\\\n\\\\n Default value: false\\\\n\\\\n --dry-run | --dr | --dry (boolean)\\\\n\\\\n Display the outcome of the initialization without saving\\\\n\\\\n --edit | -e (boolean)\\\\n\\\\n Open in editor after initializing the configuration\\\\n\\\\n --overwrite | --ow (boolean)\\\\n\\\\n Replaces an existing configuration with a new configuration\\\\n\\\\n Default value: false\\\\n\\\\n --for-sure | -f (boolean)\\\\n\\\\n Confirms the overwrite option\\\\n\\\\n Default value: false\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --editor | --ed (string)\\\\n\\\\n Editor that overrides the default editor for this file type. Set the option to\\\\n the editor's executable file location or the program's name: ie \\\\\\"--editor\\\\n notepad\\\\\\"\\\\n\\\\n APIML CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n Host name of the mainframe running the API Mediation Layer.\\\\n\\\\n --port | -P (number)\\\\n\\\\n Port number of API Mediation Layer on the mainframe.\\\\n\\\\n --user | -u (string)\\\\n\\\\n User name to authenticate to the API Mediation Layer on the mainframe.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Password to authenticate to the API Mediation Layer on the mainframe.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API Mediation Layer. Omit this option\\\\n to use the default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API Mediation Layer.\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use to authenticate to the API Mediation\\\\n Layer\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use to authenticate to the API\\\\n Mediation Layer\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n auto-init\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Automatically generate a config from APIML\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe config auto-init [options]\\\\n\\\\n AUTOMATIC CONFIG INITIALIZATION OPTIONS\\\\n ---------------------------------------\\\\n\\\\n --user-config | --uc (boolean)\\\\n\\\\n Save config in the user layer\\\\n\\\\n Default value: false\\\\n\\\\n --global-config | --gc (boolean)\\\\n\\\\n Save config in the global layer\\\\n\\\\n Default value: false\\\\n\\\\n --dry-run | --dr | --dry (boolean)\\\\n\\\\n Display the outcome of the initialization without saving\\\\n\\\\n --edit | -e (boolean)\\\\n\\\\n Open in editor after initializing the configuration\\\\n\\\\n --overwrite | --ow (boolean)\\\\n\\\\n Replaces an existing configuration with a new configuration\\\\n\\\\n Default value: false\\\\n\\\\n --for-sure | -f (boolean)\\\\n\\\\n Confirms the overwrite option\\\\n\\\\n Default value: false\\\\n\\\\n APIML CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n Host name of the mainframe running the API Mediation Layer.\\\\n\\\\n --port | -P (number)\\\\n\\\\n Port number of API Mediation Layer on the mainframe.\\\\n\\\\n --user | -u (string)\\\\n\\\\n User name to authenticate to the API Mediation Layer on the mainframe.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Password to authenticate to the API Mediation Layer on the mainframe.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API Mediation Layer. Omit this option\\\\n to use the default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API Mediation Layer.\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use to authenticate to the API Mediation\\\\n Layer\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use to authenticate to the API\\\\n Mediation Layer\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n auto-init\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Automatically generate a config from APIML.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe config auto-init [options]\\\\n\\\\n AUTOMATIC CONFIG INITIALIZATION OPTIONS\\\\n ---------------------------------------\\\\n\\\\n --user-config | --uc (boolean)\\\\n\\\\n Save config in the user layer\\\\n\\\\n Default value: false\\\\n\\\\n --global-config | --gc (boolean)\\\\n\\\\n Save config in the global layer\\\\n\\\\n Default value: false\\\\n\\\\n --dry-run | --dr | --dry (boolean)\\\\n\\\\n Display the outcome of the initialization without saving\\\\n\\\\n --edit | -e (boolean)\\\\n\\\\n Open in editor after initializing the configuration\\\\n\\\\n --overwrite | --ow (boolean)\\\\n\\\\n Replaces an existing configuration with a new configuration\\\\n\\\\n Default value: false\\\\n\\\\n --for-sure | -f (boolean)\\\\n\\\\n Confirms the overwrite option\\\\n\\\\n Default value: false\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --editor | --ed (string)\\\\n\\\\n Editor that overrides the default editor for this file type. Set the option to\\\\n the editor's executable file location or the program's name: ie \\\\\\"--editor\\\\n notepad\\\\\\"\\\\n\\\\n APIML CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n Host name of the mainframe running the API Mediation Layer.\\\\n\\\\n --port | -P (number)\\\\n\\\\n Port number of API Mediation Layer on the mainframe.\\\\n\\\\n --user | -u (string)\\\\n\\\\n User name to authenticate to the API Mediation Layer on the mainframe.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Password to authenticate to the API Mediation Layer on the mainframe.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API Mediation Layer. Omit this option\\\\n to use the default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API Mediation Layer.\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use to authenticate to the API Mediation\\\\n Layer\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use to authenticate to the API\\\\n Mediation Layer\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/config/auto-init/__system__/cli.config.auto-init.system.test.ts b/packages/cli/__tests__/config/auto-init/__system__/cli.config.auto-init.system.test.ts index b8c60c666c..863f93d0ef 100644 --- a/packages/cli/__tests__/config/auto-init/__system__/cli.config.auto-init.system.test.ts +++ b/packages/cli/__tests__/config/auto-init/__system__/cli.config.auto-init.system.test.ts @@ -47,7 +47,8 @@ describe("config auto-init without profile", () => { ); const config = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, "zowe.config.json")).toString(); - const profiles = JSONC.parse(config).profiles; + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + const profiles = (JSONC.parse(config) as any).profiles ; let zosmfExists = false; let baseExists = false; let baseProperties; @@ -90,8 +91,9 @@ describe("config auto-init without profile", () => { it("should successfully issue the auto-init command and merge with existing config", () => { let config = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, "zowe.config.json")).toString(); - const configJson = JSONC.parse(config); - configJson.profiles.base.properties = {}; + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + const configJson = JSONC.parse(config) as any; + configJson.profiles.project_base.properties = {}; config = JSONC.stringify(configJson, null, 4); fs.writeFileSync(path.join(TEST_ENVIRONMENT.workingDir, "zowe.config.json"), config); @@ -107,7 +109,8 @@ describe("config auto-init without profile", () => { ); config = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, "zowe.config.json")).toString(); - const profiles = JSONC.parse(config).profiles; + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + const profiles = (JSONC.parse(config) as any).profiles; let zosmfExists = false; let baseExists = false; let baseProperties; @@ -185,7 +188,8 @@ describe("config auto-init without profile and with certificates", () => { ); const config = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, "zowe.config.json")).toString(); - const profiles = JSONC.parse(config).profiles; + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + const profiles = (JSONC.parse(config) as any).profiles; let zosmfExists = false; let baseExists = false; let baseProperties; @@ -233,9 +237,10 @@ describe("config auto-init without profile and with certificates", () => { process.stdout.write("Skipping test because pem cert file is undefined\n"); } else { let config = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, "zowe.config.json")).toString(); - const configJson = JSONC.parse(config); - configJson.profiles.base.properties = {}; - configJson.profiles.base.secure = []; + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + const configJson = JSONC.parse(config) as any; + configJson.profiles.project_base.properties = {}; + configJson.profiles.project_base.secure = []; config = JSONC.stringify(configJson, null, 4); fs.writeFileSync(path.join(TEST_ENVIRONMENT.workingDir, "zowe.config.json"), config); @@ -251,7 +256,8 @@ describe("config auto-init without profile and with certificates", () => { ); config = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, "zowe.config.json")).toString(); - const profiles = JSONC.parse(config).profiles; + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + const profiles = (JSONC.parse(config) as any).profiles; let zosmfExists = false; let baseExists = false; let baseProperties; @@ -315,7 +321,8 @@ describe("config auto-init with profile", () => { const response = runCliScript(__dirname + "/__scripts__/config_auto_init_profile.sh", TEST_ENVIRONMENT); const config = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, "zowe.config.json")).toString(); - const profiles = JSONC.parse(config).profiles; + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + const profiles = (JSONC.parse(config) as any).profiles; let zosmfExists = false; let baseExists = false; let baseProperties; @@ -374,7 +381,8 @@ describe("config auto-init with profile and certificates", () => { const response = runCliScript(__dirname + "/__scripts__/config_auto_init_profile.sh", TEST_ENVIRONMENT); const config = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, "zowe.config.json")).toString(); - const profiles = JSONC.parse(config).profiles; + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + const profiles = (JSONC.parse(config) as any).profiles; let zosmfExists = false; let baseExists = false; let baseProperties; diff --git a/packages/cli/__tests__/config/auto-init/__unit__/ApimlAutoInitHandler.unit.test.ts b/packages/cli/__tests__/config/auto-init/__unit__/ApimlAutoInitHandler.unit.test.ts index 8ffc0e1a32..73c731ca5b 100644 --- a/packages/cli/__tests__/config/auto-init/__unit__/ApimlAutoInitHandler.unit.test.ts +++ b/packages/cli/__tests__/config/auto-init/__unit__/ApimlAutoInitHandler.unit.test.ts @@ -86,16 +86,17 @@ describe("ApimlAutoInitHandler", () => { }, { arguments: { $0: "fake", - _: ["fake"] + _: ["fake"], } }); expect(mockGetPluginApimlConfigs).toHaveBeenCalledTimes(1); expect(mockGetServicesByConfig).toHaveBeenCalledTimes(1); expect(mockConvertApimlProfileInfoToProfileConfig).toHaveBeenCalledTimes(1); expect(mockLogin).toHaveBeenCalledTimes(1); - expect(response.profiles.base.secure).toContain("tokenValue"); - expect(response.profiles.base.properties.tokenType).toEqual(SessConstants.TOKEN_TYPE_APIML); - expect(response.profiles.base.properties.tokenValue).toEqual("fakeToken"); + const baseProfName = "project_base"; + expect(response.profiles[baseProfName].secure).toContain("tokenValue"); + expect(response.profiles[baseProfName].properties.tokenType).toEqual(SessConstants.TOKEN_TYPE_APIML); + expect(response.profiles[baseProfName].properties.tokenValue).toEqual("fakeToken"); }); it("should not have changed - tokenType and tokenValue", async () => { @@ -141,9 +142,11 @@ describe("ApimlAutoInitHandler", () => { expect(mockGetServicesByConfig).toHaveBeenCalledTimes(1); expect(mockConvertApimlProfileInfoToProfileConfig).toHaveBeenCalledTimes(1); expect(mockLogin).toHaveBeenCalledTimes(0); - expect(response.profiles.base.secure).toContain("tokenValue"); - expect(response.profiles.base.properties.tokenType).toEqual(SessConstants.TOKEN_TYPE_APIML); - expect(response.profiles.base.properties.tokenValue).toEqual("fakeToken"); + + const baseProfName = "project_base"; + expect(response.profiles[baseProfName].secure).toContain("tokenValue"); + expect(response.profiles[baseProfName].properties.tokenType).toEqual(SessConstants.TOKEN_TYPE_APIML); + expect(response.profiles[baseProfName].properties.tokenValue).toEqual("fakeToken"); }); it("should not have changed - PEM Certificates", async () => { @@ -190,9 +193,11 @@ describe("ApimlAutoInitHandler", () => { expect(mockGetServicesByConfig).toHaveBeenCalledTimes(1); expect(mockConvertApimlProfileInfoToProfileConfig).toHaveBeenCalledTimes(1); expect(mockLogin).toHaveBeenCalledTimes(1); - expect(response.profiles.base.secure).toContain("tokenValue"); - expect(response.profiles.base.properties.tokenType).toEqual(SessConstants.TOKEN_TYPE_APIML); - expect(response.profiles.base.properties.tokenValue).toEqual("fakeToken"); + + const baseProfName = "project_base"; + expect(response.profiles[baseProfName].secure).toContain("tokenValue"); + expect(response.profiles[baseProfName].properties.tokenType).toEqual(SessConstants.TOKEN_TYPE_APIML); + expect(response.profiles[baseProfName].properties.tokenValue).toEqual("fakeToken"); }); it("should not have changed - secure fields with existing non-default base profile", async () => { @@ -380,7 +385,7 @@ describe("ApimlAutoInitHandler", () => { expect(mockGetServicesByConfig).toHaveBeenCalledTimes(1); expect(mockConvertApimlProfileInfoToProfileConfig).toHaveBeenCalledTimes(1); expect(mockLogin).toHaveBeenCalledTimes(1); - expect(response.profiles.base.properties.rejectUnauthorized).toEqual(true); + expect(response.profiles["project_base"].properties.rejectUnauthorized).toEqual(true); }); it("should not have changed - rejectUnauthorized flag false", async () => { @@ -428,7 +433,7 @@ describe("ApimlAutoInitHandler", () => { expect(mockGetServicesByConfig).toHaveBeenCalledTimes(1); expect(mockConvertApimlProfileInfoToProfileConfig).toHaveBeenCalledTimes(1); expect(mockLogin).toHaveBeenCalledTimes(1); - expect(response.profiles.base.properties.rejectUnauthorized).toEqual(false); + expect(response.profiles["project_base"].properties.rejectUnauthorized).toEqual(false); }); it("should not have changed - a condition that shouldn't ever happen", async () => { @@ -472,9 +477,11 @@ describe("ApimlAutoInitHandler", () => { expect(mockGetServicesByConfig).toHaveBeenCalledTimes(1); expect(mockConvertApimlProfileInfoToProfileConfig).toHaveBeenCalledTimes(1); expect(mockLogin).toHaveBeenCalledTimes(0); - expect(response.profiles.base.secure).not.toContain("tokenValue"); - expect(response.profiles.base.properties.tokenType).not.toBeDefined(); - expect(response.profiles.base.properties.tokenValue).not.toBeDefined(); + + const baseProfName = "project_base"; + expect(response.profiles[baseProfName].secure).not.toContain("tokenValue"); + expect(response.profiles[baseProfName].properties.tokenType).not.toBeDefined(); + expect(response.profiles[baseProfName].properties.tokenValue).not.toBeDefined(); }); it("should throw an error if an error 403 is experienced", async () => { diff --git a/packages/cli/__tests__/daemon/__unit__/DaemonClient.unit.test.ts b/packages/cli/__tests__/daemon/__unit__/DaemonClient.unit.test.ts index 8d760c8344..b1ced357ff 100644 --- a/packages/cli/__tests__/daemon/__unit__/DaemonClient.unit.test.ts +++ b/packages/cli/__tests__/daemon/__unit__/DaemonClient.unit.test.ts @@ -13,7 +13,7 @@ jest.mock("net"); jest.mock("@zowe/imperative"); import * as net from "net"; import * as stream from "stream"; -import getStream = require("get-stream"); +import { text } from "stream/consumers"; import { DaemonClient } from "../../../src/daemon/DaemonClient"; import { IDaemonResponse, Imperative, IO } from "@zowe/imperative"; @@ -338,7 +338,7 @@ describe("DaemonClient tests", () => { client.once("readable", () => resolve(client.read())); }); const stdinStream = (daemonClient as any).createStdinStream(firstChunk, alphabet.length); - expect(await getStream(stdinStream)).toBe(alphabet); + expect(await text(stdinStream)).toBe(alphabet); }); it("should not process data when received from another user", () => { diff --git a/packages/cli/__tests__/daemon/__unit__/disable/__snapshots__/Disable.definition.unit.test.ts.snap b/packages/cli/__tests__/daemon/__unit__/disable/__snapshots__/Disable.definition.unit.test.ts.snap index 6e99427591..768163d607 100644 --- a/packages/cli/__tests__/daemon/__unit__/disable/__snapshots__/Disable.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/daemon/__unit__/disable/__snapshots__/Disable.definition.unit.test.ts.snap @@ -2,7 +2,7 @@ exports[`daemon disable definition should not have changed 1`] = ` Object { - "description": "Disables daemon-mode operation of the Zowe CLI.", + "description": "Disable daemon-mode operation of the Zowe CLI.", "examples": Array [ Object { "description": "Disable daemon-mode", @@ -10,6 +10,7 @@ Object { }, ], "name": "disable", + "summary": "Disable daemon-mode operation of the Zowe CLI", "type": "command", } `; diff --git a/packages/cli/__tests__/daemon/__unit__/enable/__snapshots__/Enable.definition.unit.test.ts.snap b/packages/cli/__tests__/daemon/__unit__/enable/__snapshots__/Enable.definition.unit.test.ts.snap index 5b49455654..695530d528 100644 --- a/packages/cli/__tests__/daemon/__unit__/enable/__snapshots__/Enable.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/daemon/__unit__/enable/__snapshots__/Enable.definition.unit.test.ts.snap @@ -2,7 +2,7 @@ exports[`daemon enable definition should not have changed 1`] = ` Object { - "description": "Enables daemon-mode operation of the Zowe CLI. You only need to run the enable command once after each new installation of the Zowe CLI. Afterwards, any zowe command will automatically start a daemon as needed.", + "description": "Enable daemon-mode operation of the Zowe CLI. You only need to run the enable command once after each new installation of the Zowe CLI. Afterwards, any zowe command will automatically start a daemon as needed.", "examples": Array [ Object { "description": "Enable daemon-mode", @@ -10,6 +10,7 @@ Object { }, ], "name": "enable", + "summary": "Enable daemon-mode operation of the Zowe CLI", "type": "command", } `; diff --git a/packages/cli/__tests__/daemon/__unit__/restart/__snapshots__/restart.definition.unit.test.ts.snap b/packages/cli/__tests__/daemon/__unit__/restart/__snapshots__/restart.definition.unit.test.ts.snap index 475757f497..f0ccfa63bd 100644 --- a/packages/cli/__tests__/daemon/__unit__/restart/__snapshots__/restart.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/daemon/__unit__/restart/__snapshots__/restart.definition.unit.test.ts.snap @@ -1,6 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP - exports[`daemon restart definition should not have changed 1`] = ` Object { "description": "Restart the Zowe CLI daemon.", @@ -11,6 +10,7 @@ Object { }, ], "name": "restart", + "summary": "Restart the Zowe CLI daemon", "type": "command", } `; diff --git a/packages/cli/__tests__/help/__integration__/BrightHelpTests.integration.test.ts b/packages/cli/__tests__/help/__integration__/ZoweHelpTests.integration.test.ts similarity index 100% rename from packages/cli/__tests__/help/__integration__/BrightHelpTests.integration.test.ts rename to packages/cli/__tests__/help/__integration__/ZoweHelpTests.integration.test.ts diff --git a/packages/cli/__tests__/help/__integration__/__snapshots__/BrightHelpTests.integration.test.ts.snap b/packages/cli/__tests__/help/__integration__/__snapshots__/ZoweHelpTests.integration.test.ts.snap similarity index 89% rename from packages/cli/__tests__/help/__integration__/__snapshots__/BrightHelpTests.integration.test.ts.snap rename to packages/cli/__tests__/help/__integration__/__snapshots__/ZoweHelpTests.integration.test.ts.snap index 23878c0237..4b62718b9f 100644 --- a/packages/cli/__tests__/help/__integration__/__snapshots__/BrightHelpTests.integration.test.ts.snap +++ b/packages/cli/__tests__/help/__integration__/__snapshots__/ZoweHelpTests.integration.test.ts.snap @@ -28,9 +28,7 @@ exports[`Root level help tests top level help should contain support link 1`] = auth Connect to Zowe API ML authentication service config Manage JSON project and global configuration daemon Daemon operations - plugins Install and manage plug-ins. - profiles Create and manage configuration profiles. - (deprecated) + plugins Install and manage plug-ins provisioning | pv Perform z/OSMF provisioning tasks zos-console | console Issue z/OS console commands and collect responses diff --git a/packages/cli/__tests__/provisioning/__integration__/delete/__snapshots__/cli.provisioning.delete.integration.test.ts.snap b/packages/cli/__tests__/provisioning/__integration__/delete/__snapshots__/cli.provisioning.delete.integration.test.ts.snap index 61ca7ab4ef..b29ffc38a1 100644 --- a/packages/cli/__tests__/provisioning/__integration__/delete/__snapshots__/cli.provisioning.delete.integration.test.ts.snap +++ b/packages/cli/__tests__/provisioning/__integration__/delete/__snapshots__/cli.provisioning.delete.integration.test.ts.snap @@ -17,7 +17,7 @@ exports[`provisioning delete should display the help 1`] = ` COMMANDS -------- - template | tem Provision a published software service template. + template | tem Provision a published software service template GLOBAL OPTIONS -------------- @@ -42,38 +42,8 @@ exports[`provisioning delete should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: delete.\\", - \\"stdout\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Deletes instance previously provisioned with z/OSMF cloud provisioning services.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe provisioning delete \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n instance | i Deletes instance.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Deletes instance previously provisioned with z/OSMF cloud provisioning services.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe provisioning delete \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n instance | i Deletes instance\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Deletes instance previously provisioned with z/OSMF cloud provisioning services.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe provisioning delete \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n instance | i Deletes instance.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" + \\"data\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Deletes instance previously provisioned with z/OSMF cloud provisioning services.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe provisioning delete \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n instance | i Deletes instance\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" }" `; - -exports[`provisioning delete should fail with invalid option 1`] = ` -"Command Error: -Unknown arguments: foo-bar, fooBar -Command failed due to improper syntax -Command entered: \\"provisioning delete instance --foo-bar\\" -Available commands are \\"instance\\". -Use \\"zowe provisioning delete --help\\" to view groups, commands, and options. -Error Details: -Unknown arguments: foo-bar, fooBar -" -`; - -exports[`provisioning delete should fail with invalid option 2`] = `""`; - -exports[`provisioning delete should fail with invalid parameter 1`] = ` -"Command Error: -Unknown argument: foobar -Command failed due to improper syntax -Did you mean: provisioning delete i? - -Command entered: \\"provisioning delete foobar\\" -Available commands are \\"instance\\". -Use \\"zowe provisioning delete --help\\" to view groups, commands, and options. -Error Details: -Unknown argument: foobar -" -`; - -exports[`provisioning delete should fail with invalid parameter 2`] = `""`; diff --git a/packages/cli/__tests__/provisioning/__integration__/delete/cli.provisioning.delete.integration.test.ts b/packages/cli/__tests__/provisioning/__integration__/delete/cli.provisioning.delete.integration.test.ts index bd99e53744..18987e8ef8 100644 --- a/packages/cli/__tests__/provisioning/__integration__/delete/cli.provisioning.delete.integration.test.ts +++ b/packages/cli/__tests__/provisioning/__integration__/delete/cli.provisioning.delete.integration.test.ts @@ -36,14 +36,25 @@ describe("provisioning delete", () => { it("should fail with invalid parameter", async () => { const response = runCliScript(__dirname + "/__scripts__/delete_invalid_parameter.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); - expect(response.stderr.toString()).toMatchSnapshot(); - expect(response.stdout.toString()).toMatchSnapshot(); + expect(response.stdout.toString()).toBe(''); + expect(response.stderr.toString()).toContain('Unknown argument: foobar'); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Did you mean: provisioning delete'); + expect(response.stderr.toString()).toContain('Command entered: "provisioning delete foobar"'); + expect(response.stderr.toString()).toContain('Available commands are "instance".'); + expect(response.stderr.toString()).toContain('Use "zowe provisioning delete --help" to view groups, commands, and options.'); + expect(response.stderr.toString()).toContain('Error: Unknown argument: foobar'); }); it("should fail with invalid option", async () => { const response = runCliScript(__dirname + "/__scripts__/delete_invalid_option.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); - expect(response.stderr.toString()).toMatchSnapshot(); - expect(response.stdout.toString()).toMatchSnapshot(); + expect(response.stdout.toString()).toBe(''); + expect(response.stderr.toString()).toContain('Unknown arguments: foo-bar, fooBar'); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Command entered: "provisioning delete instance --foo-bar"'); + expect(response.stderr.toString()).toContain('Available commands are "instance".'); + expect(response.stderr.toString()).toContain('Use "zowe provisioning delete --help" to view groups, commands, and options.'); + expect(response.stderr.toString()).toContain('Error: Unknown arguments: foo-bar, fooBar'); }); }); diff --git a/packages/cli/__tests__/provisioning/__integration__/perform/__snapshots__/cli.provisioning.perform.integration.test.ts.snap b/packages/cli/__tests__/provisioning/__integration__/perform/__snapshots__/cli.provisioning.perform.integration.test.ts.snap index c8436252bc..58a0363abe 100644 --- a/packages/cli/__tests__/provisioning/__integration__/perform/__snapshots__/cli.provisioning.perform.integration.test.ts.snap +++ b/packages/cli/__tests__/provisioning/__integration__/perform/__snapshots__/cli.provisioning.perform.integration.test.ts.snap @@ -17,7 +17,7 @@ exports[`provisioning perform should display the help 1`] = ` COMMANDS -------- - action | act Perform instance actions. + action | act Perform instance actions GLOBAL OPTIONS -------------- @@ -42,8 +42,8 @@ exports[`provisioning perform should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: perform.\\", - \\"stdout\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Perform actions against instances provisioned with z/OSMF.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe provisioning perform \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n action | act Perform instance actions.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Perform actions against instances provisioned with z/OSMF.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe provisioning perform \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n action | act Perform instance actions\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Perform actions against instances provisioned with z/OSMF.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe provisioning perform \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n action | act Perform instance actions.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" + \\"data\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Perform actions against instances provisioned with z/OSMF.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe provisioning perform \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n action | act Perform instance actions\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/provisioning/__integration__/provision/__snapshots__/cli.provisioning.provision.integration.test.ts.snap b/packages/cli/__tests__/provisioning/__integration__/provision/__snapshots__/cli.provisioning.provision.integration.test.ts.snap index b91aec755f..4038138db3 100644 --- a/packages/cli/__tests__/provisioning/__integration__/provision/__snapshots__/cli.provisioning.provision.integration.test.ts.snap +++ b/packages/cli/__tests__/provisioning/__integration__/provision/__snapshots__/cli.provisioning.provision.integration.test.ts.snap @@ -17,7 +17,7 @@ exports[`provisioning provision should display the help 1`] = ` COMMANDS -------- - template | tem Provision a published software service template. + template | tem Provision a published software service template GLOBAL OPTIONS -------------- @@ -42,38 +42,8 @@ exports[`provisioning provision should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: provision.\\", - \\"stdout\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Using z/OSMF cloud provisioning services provision available templates.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe provisioning provision \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n template | tem Provision a published software service template.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Using z/OSMF cloud provisioning services provision available templates.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe provisioning provision \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n template | tem Provision a published software service template\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Using z/OSMF cloud provisioning services provision available templates.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe provisioning provision \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n template | tem Provision a published software service template.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" + \\"data\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Using z/OSMF cloud provisioning services provision available templates.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe provisioning provision \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n template | tem Provision a published software service template\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" }" `; - -exports[`provisioning provision should fail with invalid option 1`] = ` -"Command Error: -Unknown arguments: foo-bar, fooBar -Command failed due to improper syntax -Command entered: \\"provisioning provision template --foo-bar\\" -Available commands are \\"template\\". -Use \\"zowe provisioning provision --help\\" to view groups, commands, and options. -Error Details: -Unknown arguments: foo-bar, fooBar -" -`; - -exports[`provisioning provision should fail with invalid option 2`] = `""`; - -exports[`provisioning provision should fail with invalid parameter 1`] = ` -"Command Error: -Unknown argument: foobar -Command failed due to improper syntax -Did you mean: provisioning provision tem? - -Command entered: \\"provisioning provision foobar\\" -Available commands are \\"template\\". -Use \\"zowe provisioning provision --help\\" to view groups, commands, and options. -Error Details: -Unknown argument: foobar -" -`; - -exports[`provisioning provision should fail with invalid parameter 2`] = `""`; diff --git a/packages/cli/__tests__/provisioning/__integration__/provision/cli.provisioning.provision.integration.test.ts b/packages/cli/__tests__/provisioning/__integration__/provision/cli.provisioning.provision.integration.test.ts index e44f76c8db..b2dab4ee8e 100644 --- a/packages/cli/__tests__/provisioning/__integration__/provision/cli.provisioning.provision.integration.test.ts +++ b/packages/cli/__tests__/provisioning/__integration__/provision/cli.provisioning.provision.integration.test.ts @@ -36,14 +36,25 @@ describe("provisioning provision", () => { it("should fail with invalid parameter", async () => { const response = runCliScript(__dirname + "/__scripts__/provision_invalid_parameter.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); - expect(response.stderr.toString()).toMatchSnapshot(); - expect(response.stdout.toString()).toMatchSnapshot(); + expect(response.stdout.toString()).toBe(''); + expect(response.stderr.toString()).toContain('Unknown argument: foobar'); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Did you mean: provisioning provision'); + expect(response.stderr.toString()).toContain('Command entered: "provisioning provision foobar"'); + expect(response.stderr.toString()).toContain('Available commands are "template".'); + expect(response.stderr.toString()).toContain('Use "zowe provisioning provision --help" to view groups, commands, and options.'); + expect(response.stderr.toString()).toContain('Error: Unknown argument: foobar'); }); it("should fail with invalid option", async () => { const response = runCliScript(__dirname + "/__scripts__/provision_invalid_option.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); - expect(response.stderr.toString()).toMatchSnapshot(); - expect(response.stdout.toString()).toMatchSnapshot(); + expect(response.stdout.toString()).toBe(''); + expect(response.stderr.toString()).toContain('Unknown arguments: foo-bar, fooBar'); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Command entered: "provisioning provision template --foo-bar"'); + expect(response.stderr.toString()).toContain('Available commands are "template".'); + expect(response.stderr.toString()).toContain('Use "zowe provisioning provision --help" to view groups, commands, and options.'); + expect(response.stderr.toString()).toContain('Error: Unknown arguments: foo-bar, fooBar'); }); }); diff --git a/packages/cli/__tests__/provisioning/__system__/list/instanceInfo/cli.provisioning.instanceInfo.system.test.ts b/packages/cli/__tests__/provisioning/__system__/list/instanceInfo/cli.provisioning.instanceInfo.system.test.ts index 1366786404..2e559e0326 100644 --- a/packages/cli/__tests__/provisioning/__system__/list/instanceInfo/cli.provisioning.instanceInfo.system.test.ts +++ b/packages/cli/__tests__/provisioning/__system__/list/instanceInfo/cli.provisioning.instanceInfo.system.test.ts @@ -43,6 +43,7 @@ describe("provisioning list instance-info", () => { instanceID = instance["object-id"]; instanceName = instance["external-name"]; Imperative.console.info(`Provisioned instance: ${instanceName}`); + if (instanceID == null) { throw Error("Cannot continue test - instance ID is undefined"); } }, ProvisioningTestUtils.MAX_TIMEOUT_TIME); it( diff --git a/packages/cli/__tests__/provisioning/__system__/list/instanceVariables/cli.provisioning.instanceVariables.system.test.ts b/packages/cli/__tests__/provisioning/__system__/list/instanceVariables/cli.provisioning.instanceVariables.system.test.ts index b6119c8589..cdb6501a2c 100644 --- a/packages/cli/__tests__/provisioning/__system__/list/instanceVariables/cli.provisioning.instanceVariables.system.test.ts +++ b/packages/cli/__tests__/provisioning/__system__/list/instanceVariables/cli.provisioning.instanceVariables.system.test.ts @@ -38,6 +38,7 @@ describe("provisioning list instance-variables", () => { instance = await ProvisioningTestUtils.getProvisionedInstance(REAL_SESSION, ProvisioningConstants.ZOSMF_VERSION, templateName); instanceID = instance["object-id"]; Imperative.console.info(`Provisioned instance: ${instance["external-name"]}`); + if (instanceID == null) { throw Error("Cannot continue test - instance ID is undefined"); } }, ProvisioningTestUtils.MAX_TIMEOUT_TIME); it("should display instance info(expects first instance in registry to have variables)", async () => { diff --git a/packages/cli/__tests__/provisioning/__system__/perform/cli.provisioning.perform.action.system.test.ts b/packages/cli/__tests__/provisioning/__system__/perform/cli.provisioning.perform.action.system.test.ts index 04d98a8715..880524fa09 100644 --- a/packages/cli/__tests__/provisioning/__system__/perform/cli.provisioning.perform.action.system.test.ts +++ b/packages/cli/__tests__/provisioning/__system__/perform/cli.provisioning.perform.action.system.test.ts @@ -43,6 +43,7 @@ describe("provisioning perform action", () => { instanceID = instance["object-id"]; instanceName = instance["external-name"]; Imperative.console.info(`Provisioned instance: ${instanceName}`); + if (instanceID == null) { throw Error("Cannot continue test - instance ID is undefined"); } }, ProvisioningTestUtils.MAX_TIMEOUT_TIME); it("should successfully perform checkStatus action", async () => { diff --git a/packages/cli/__tests__/provisioning/__unit__/delete/__snapshots__/Delete.definition.unit.test.ts.snap b/packages/cli/__tests__/provisioning/__unit__/delete/__snapshots__/Delete.definition.unit.test.ts.snap index 1161837de2..2482746d1a 100644 --- a/packages/cli/__tests__/provisioning/__unit__/delete/__snapshots__/Delete.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/provisioning/__unit__/delete/__snapshots__/Delete.definition.unit.test.ts.snap @@ -7,7 +7,7 @@ Object { ], "description": "Deletes instance previously provisioned with z/OSMF cloud provisioning services.", "name": "delete", - "summary": "Delete instance.", + "summary": "Delete instance", "type": "group", } `; diff --git a/packages/cli/__tests__/provisioning/__unit__/delete/instance/DeleteInstance.handler.unit.test.ts b/packages/cli/__tests__/provisioning/__unit__/delete/instance/DeleteInstance.handler.unit.test.ts index 383b7df853..a82af61b33 100644 --- a/packages/cli/__tests__/provisioning/__unit__/delete/instance/DeleteInstance.handler.unit.test.ts +++ b/packages/cli/__tests__/provisioning/__unit__/delete/instance/DeleteInstance.handler.unit.test.ts @@ -19,17 +19,13 @@ import { ListRegistryInstances, ProvisioningConstants } from "@zowe/provisioning-for-zowe-sdk"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["provisioning", "delete", "instance"], - definition: DeleteInstanceDefinition.DeleteInstanceDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: DeleteInstanceDefinition.DeleteInstanceDefinition }); describe("delete deprovisioned instance handler tests", () => { diff --git a/packages/cli/__tests__/provisioning/__unit__/delete/instance/__snapshots__/DeleteInstance.definition.unit.test.ts.snap b/packages/cli/__tests__/provisioning/__unit__/delete/instance/__snapshots__/DeleteInstance.definition.unit.test.ts.snap index 8601c97a9c..15bd77fb34 100644 --- a/packages/cli/__tests__/provisioning/__unit__/delete/instance/__snapshots__/DeleteInstance.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/provisioning/__unit__/delete/instance/__snapshots__/DeleteInstance.definition.unit.test.ts.snap @@ -26,7 +26,7 @@ Object { "zosmf", ], }, - "summary": "Deletes instance.", + "summary": "Deletes instance", "type": "command", } `; diff --git a/packages/cli/__tests__/provisioning/__unit__/list/catalogTemplates/CatalogTemplates.handler.unit.test.ts b/packages/cli/__tests__/provisioning/__unit__/list/catalogTemplates/CatalogTemplates.handler.unit.test.ts index ee68d4ddc1..ad11da8448 100644 --- a/packages/cli/__tests__/provisioning/__unit__/list/catalogTemplates/CatalogTemplates.handler.unit.test.ts +++ b/packages/cli/__tests__/provisioning/__unit__/list/catalogTemplates/CatalogTemplates.handler.unit.test.ts @@ -14,10 +14,7 @@ import { ListCatalogTemplates } from "@zowe/provisioning-for-zowe-sdk"; import { IHandlerParameters } from "@zowe/imperative"; import * as Handler from "../../../../../src/provisioning/list/catalogTemplates/CatalogTemplates.handler"; import { catalogTemplates } from "../../../../../src/provisioning/list/catalogTemplates/CatalogTemplates.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; jest.mock("../../../../../../../packages/provisioning/src/ListCatalogTemplates"); @@ -25,8 +22,7 @@ jest.mock("../../../../../../../packages/provisioning/src/ListCatalogTemplates") const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["provisioning", "list", "catalog-templates"], - definition: catalogTemplates, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: catalogTemplates }); describe("list catalog templates handler tests", () => { diff --git a/packages/cli/__tests__/provisioning/__unit__/list/catalogTemplates/__snapshots__/CatalogTemplates.definition.unit.test.ts.snap b/packages/cli/__tests__/provisioning/__unit__/list/catalogTemplates/__snapshots__/CatalogTemplates.definition.unit.test.ts.snap index af82548f2e..d3c7099f28 100644 --- a/packages/cli/__tests__/provisioning/__unit__/list/catalogTemplates/__snapshots__/CatalogTemplates.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/provisioning/__unit__/list/catalogTemplates/__snapshots__/CatalogTemplates.definition.unit.test.ts.snap @@ -28,7 +28,7 @@ Object { "zosmf", ], }, - "summary": "List z/OSMF published catalog templates.", + "summary": "List z/OSMF published catalog templates", "type": "command", } `; diff --git a/packages/cli/__tests__/provisioning/__unit__/list/instanceInfo/InstanceInfo.handler.unit.test.ts b/packages/cli/__tests__/provisioning/__unit__/list/instanceInfo/InstanceInfo.handler.unit.test.ts index a590bc1d97..b0c60c198d 100644 --- a/packages/cli/__tests__/provisioning/__unit__/list/instanceInfo/InstanceInfo.handler.unit.test.ts +++ b/packages/cli/__tests__/provisioning/__unit__/list/instanceInfo/InstanceInfo.handler.unit.test.ts @@ -18,17 +18,13 @@ import { import * as Handler from "../../../../../src/provisioning/list/instanceInfo/InstanceInfo.handler"; import { instanceInfo } from "../../../../../src/provisioning/list/instanceInfo/InstanceInfo.definition"; import { ProvisioningListMocks } from "../../../__resources__/ProvisioningListMocks"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["provisioning", "list", "instance-info"], - definition: instanceInfo, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: instanceInfo }); describe("list instance info handler tests", () => { diff --git a/packages/cli/__tests__/provisioning/__unit__/list/instanceInfo/__snapshots__/InstanceInfo.definition.unit.test.ts.snap b/packages/cli/__tests__/provisioning/__unit__/list/instanceInfo/__snapshots__/InstanceInfo.definition.unit.test.ts.snap index 3d0e2d8765..c9870593b7 100644 --- a/packages/cli/__tests__/provisioning/__unit__/list/instanceInfo/__snapshots__/InstanceInfo.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/provisioning/__unit__/list/instanceInfo/__snapshots__/InstanceInfo.definition.unit.test.ts.snap @@ -54,7 +54,7 @@ full - all available information "zosmf", ], }, - "summary": "List Provisioned Instance Details.", + "summary": "List Provisioned Instance Details", "type": "command", } `; diff --git a/packages/cli/__tests__/provisioning/__unit__/list/instanceVars/InstanceVariables.handler.unit.test.ts b/packages/cli/__tests__/provisioning/__unit__/list/instanceVars/InstanceVariables.handler.unit.test.ts index 631ec695a0..ac0b24d4b9 100644 --- a/packages/cli/__tests__/provisioning/__unit__/list/instanceVars/InstanceVariables.handler.unit.test.ts +++ b/packages/cli/__tests__/provisioning/__unit__/list/instanceVars/InstanceVariables.handler.unit.test.ts @@ -16,17 +16,13 @@ import { IHandlerParameters } from "@zowe/imperative"; import * as Handler from "../../../../../src/provisioning/list/instanceVariables/InstanceVariables.handler"; import { instanceVariables } from "../../../../../src/provisioning/list/instanceVariables/InstanceVariables.definition"; import { ProvisioningListMocks } from "../../../__resources__/ProvisioningListMocks"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["provisioning", "list", "instance-variables"], - definition: instanceVariables, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: instanceVariables }); describe("list instance variables handler tests", () => { diff --git a/packages/cli/__tests__/provisioning/__unit__/list/instanceVars/__snapshots__/InstanceVariables.definition.unit.test.ts.snap b/packages/cli/__tests__/provisioning/__unit__/list/instanceVars/__snapshots__/InstanceVariables.definition.unit.test.ts.snap index a154ad89ae..01151d2ea2 100644 --- a/packages/cli/__tests__/provisioning/__unit__/list/instanceVars/__snapshots__/InstanceVariables.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/provisioning/__unit__/list/instanceVars/__snapshots__/InstanceVariables.definition.unit.test.ts.snap @@ -27,7 +27,7 @@ Object { "zosmf", ], }, - "summary": "List Instance Variables and Values.", + "summary": "List Instance Variables and Values", "type": "command", } `; diff --git a/packages/cli/__tests__/provisioning/__unit__/list/registryInstances/RegistryInstances.handler.unit.test.ts b/packages/cli/__tests__/provisioning/__unit__/list/registryInstances/RegistryInstances.handler.unit.test.ts index b333e6cb3b..8136f7560b 100644 --- a/packages/cli/__tests__/provisioning/__unit__/list/registryInstances/RegistryInstances.handler.unit.test.ts +++ b/packages/cli/__tests__/provisioning/__unit__/list/registryInstances/RegistryInstances.handler.unit.test.ts @@ -13,10 +13,7 @@ import { ListRegistryInstances } from "@zowe/provisioning-for-zowe-sdk"; import { IHandlerParameters } from "@zowe/imperative"; import * as Handler from "../../../../../src/provisioning/list/registry/RegistryInstances.handler"; import { registryInstances } from "../../../../../src/provisioning/list/registry/RegistryInstances.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; jest.mock("@zowe/provisioning-for-zowe-sdk"); @@ -24,8 +21,7 @@ jest.mock("@zowe/provisioning-for-zowe-sdk"); const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["provisioning", "list", "catalog-templates"], - definition: registryInstances, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: registryInstances }); describe("list registry instances handler tests", () => { diff --git a/packages/cli/__tests__/provisioning/__unit__/list/registryInstances/__snapshots__/RegistryInstances.definition.unit.test.ts.snap b/packages/cli/__tests__/provisioning/__unit__/list/registryInstances/__snapshots__/RegistryInstances.definition.unit.test.ts.snap index ef614db4a3..91e4719015 100644 --- a/packages/cli/__tests__/provisioning/__unit__/list/registryInstances/__snapshots__/RegistryInstances.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/provisioning/__unit__/list/registryInstances/__snapshots__/RegistryInstances.definition.unit.test.ts.snap @@ -52,7 +52,7 @@ Object { "zosmf", ], }, - "summary": "List provisioned instances.", + "summary": "List provisioned instances", "type": "command", } `; diff --git a/packages/cli/__tests__/provisioning/__unit__/list/templateInfo/TemplateInfo.handler.unit.test.ts b/packages/cli/__tests__/provisioning/__unit__/list/templateInfo/TemplateInfo.handler.unit.test.ts index 21165a3998..35b25fb87e 100644 --- a/packages/cli/__tests__/provisioning/__unit__/list/templateInfo/TemplateInfo.handler.unit.test.ts +++ b/packages/cli/__tests__/provisioning/__unit__/list/templateInfo/TemplateInfo.handler.unit.test.ts @@ -14,17 +14,13 @@ import { ListTemplateInfo } from "@zowe/provisioning-for-zowe-sdk"; import { IHandlerParameters } from "@zowe/imperative"; import * as Handler from "../../../../../src/provisioning/list/templateInfo/TemplateInfo.handler"; import { templateInfo } from "../../../../../src/provisioning/list/templateInfo/TemplateInfo.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["provisioning", "list", "catalog-templates"], - definition: templateInfo, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: templateInfo }); describe("list template info handler tests", () => { diff --git a/packages/cli/__tests__/provisioning/__unit__/list/templateInfo/__snapshots__/TemplateInfo.definition.unit.test.ts.snap b/packages/cli/__tests__/provisioning/__unit__/list/templateInfo/__snapshots__/TemplateInfo.definition.unit.test.ts.snap index 32e7224735..df7bc175c2 100644 --- a/packages/cli/__tests__/provisioning/__unit__/list/templateInfo/__snapshots__/TemplateInfo.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/provisioning/__unit__/list/templateInfo/__snapshots__/TemplateInfo.definition.unit.test.ts.snap @@ -36,7 +36,7 @@ Object { "zosmf", ], }, - "summary": "List Published Template Details.", + "summary": "List Published Template Details", "type": "command", } `; diff --git a/packages/cli/__tests__/provisioning/__unit__/perform/__snapshots__/Perform.definition.unit.test.ts.snap b/packages/cli/__tests__/provisioning/__unit__/perform/__snapshots__/Perform.definition.unit.test.ts.snap index fc124cb936..b21a83e45d 100644 --- a/packages/cli/__tests__/provisioning/__unit__/perform/__snapshots__/Perform.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/provisioning/__unit__/perform/__snapshots__/Perform.definition.unit.test.ts.snap @@ -7,7 +7,7 @@ Object { ], "description": "Perform actions against instances provisioned with z/OSMF.", "name": "perform", - "summary": "Perform instance actions.", + "summary": "Perform instance actions", "type": "group", } `; diff --git a/packages/cli/__tests__/provisioning/__unit__/perform/action/Action.handler.unit.test.ts b/packages/cli/__tests__/provisioning/__unit__/perform/action/Action.handler.unit.test.ts index fed787cf42..6f52fccf58 100644 --- a/packages/cli/__tests__/provisioning/__unit__/perform/action/Action.handler.unit.test.ts +++ b/packages/cli/__tests__/provisioning/__unit__/perform/action/Action.handler.unit.test.ts @@ -20,17 +20,13 @@ import { import { IHandlerParameters } from "@zowe/imperative"; import * as ActionHandler from "../../../../../src/provisioning/perform/action/Action.handler"; import * as ActionDefinition from "../../../../../src/provisioning/perform/action/Action.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["provisioning", "perform", "action"], - definition: ActionDefinition.ActionDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: ActionDefinition.ActionDefinition }); describe("perform action handler tests", () => { diff --git a/packages/cli/__tests__/provisioning/__unit__/perform/action/__snapshots__/Action.definition.unit.test.ts.snap b/packages/cli/__tests__/provisioning/__unit__/perform/action/__snapshots__/Action.definition.unit.test.ts.snap index 18acff747e..d4553339ba 100644 --- a/packages/cli/__tests__/provisioning/__unit__/perform/action/__snapshots__/Action.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/provisioning/__unit__/perform/action/__snapshots__/Action.definition.unit.test.ts.snap @@ -37,7 +37,7 @@ Object { "zosmf", ], }, - "summary": "Perform instance actions.", + "summary": "Perform instance actions", "type": "command", } `; diff --git a/packages/cli/__tests__/provisioning/__unit__/provision/__snapshots__/Provision.definition.unit.test.ts.snap b/packages/cli/__tests__/provisioning/__unit__/provision/__snapshots__/Provision.definition.unit.test.ts.snap index 41a90b2d2d..90314bafb2 100644 --- a/packages/cli/__tests__/provisioning/__unit__/provision/__snapshots__/Provision.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/provisioning/__unit__/provision/__snapshots__/Provision.definition.unit.test.ts.snap @@ -7,7 +7,7 @@ Object { ], "description": "Using z/OSMF cloud provisioning services provision available templates.", "name": "provision", - "summary": "Provision published software service templates.", + "summary": "Provision published software service templates", "type": "group", } `; diff --git a/packages/cli/__tests__/provisioning/__unit__/provision/template/Template.handler.unit.test.ts b/packages/cli/__tests__/provisioning/__unit__/provision/template/Template.handler.unit.test.ts index dc8d39cb4d..42337c91ce 100644 --- a/packages/cli/__tests__/provisioning/__unit__/provision/template/Template.handler.unit.test.ts +++ b/packages/cli/__tests__/provisioning/__unit__/provision/template/Template.handler.unit.test.ts @@ -18,17 +18,13 @@ import { ProvisionTemplateData } from "../../../__resources__/ProvisionTemplateD import { IHandlerParameters, ImperativeError } from "@zowe/imperative"; import * as TemplateHandler from "../../../../../src/provisioning/provision/template/Template.handler"; import * as TemplateDefinition from "../../../../../src/provisioning/provision/template/Template.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["provisioning", "provision", "template"], - definition: TemplateDefinition.TemplateDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: TemplateDefinition.TemplateDefinition }); describe("provision template handler tests", () => { diff --git a/packages/cli/__tests__/provisioning/__unit__/provision/template/__snapshots__/Template.definition.unit.test.ts.snap b/packages/cli/__tests__/provisioning/__unit__/provision/template/__snapshots__/Template.definition.unit.test.ts.snap index f7c1c0bcab..3199de7d84 100644 --- a/packages/cli/__tests__/provisioning/__unit__/provision/template/__snapshots__/Template.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/provisioning/__unit__/provision/template/__snapshots__/Template.definition.unit.test.ts.snap @@ -95,7 +95,7 @@ e.g: \\"SYSNAME1,SYSNAME2\\".", "zosmf", ], }, - "summary": "Provision a published software service template.", + "summary": "Provision a published software service template", "type": "command", } `; diff --git a/packages/cli/__tests__/tsconfig.json b/packages/cli/__tests__/tsconfig.json index c4d748311b..4d653bc801 100644 --- a/packages/cli/__tests__/tsconfig.json +++ b/packages/cli/__tests__/tsconfig.json @@ -1,28 +1,28 @@ { - // tsconfig for test files // - "compilerOptions": { - "types": ["node", "jest"], - "lib": ["esnext"], - "target": "es2015", - "module": "commonjs", - "declaration": true, - "moduleResolution": "node", - "noImplicitAny": true, - "preserveConstEnums": true, - "experimentalDecorators": true, - "removeComments": false, - "pretty": true, - "sourceMap": true, - "newLine": "lf", - "esModuleInterop": true - }, - "include": [ - "**/*.test.ts", - "**/*.subtest.ts", - "**/__tests__/**/*" - ], - "exclude": [ - "lib", - "node_modules" - ] -} \ No newline at end of file + // tsconfig for test files // + "compilerOptions": { + "types": ["node", "jest"], + "lib": ["esnext"], + "target": "es2015", + "module": "commonjs", + "declaration": true, + "moduleResolution": "node", + "noImplicitAny": true, + "preserveConstEnums": true, + "experimentalDecorators": true, + "removeComments": false, + "pretty": true, + "sourceMap": true, + "newLine": "lf", + "esModuleInterop": true + }, + "include": [ + "**/*.test.ts", + "**/*.subtest.ts", + "**/__tests__/**/*" + ], + "exclude": [ + "lib", + "node_modules" + ] +} diff --git a/packages/cli/__tests__/workflows/__integration__/create/dataset/__snapshots__/cli.workflows.create.workflowDs.integration.test.ts.snap b/packages/cli/__tests__/workflows/__integration__/create/dataset/__snapshots__/cli.workflows.create.workflowDs.integration.test.ts.snap index e3440ad886..7ea1148b71 100644 --- a/packages/cli/__tests__/workflows/__integration__/create/dataset/__snapshots__/cli.workflows.create.workflowDs.integration.test.ts.snap +++ b/packages/cli/__tests__/workflows/__integration__/create/dataset/__snapshots__/cli.workflows.create.workflowDs.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Create workflow with data set integration test should display create wo DESCRIPTION ----------- - Create a z/OSMF workflow on a z/OS system using a Data set + Create a z/OSMF workflow on a z/OS system using a data set. USAGE ----- @@ -235,8 +235,8 @@ exports[`Create workflow with data set integration test should display create wo \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: workflow-from-data-set.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n workflow-from-data-set | wfds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create a z/OSMF workflow on a z/OS system using a Data set\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows create workflow-from-data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n workflowName\\\\t\\\\t (string)\\\\n\\\\n Name of the workflow\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --data-set | --ds (string)\\\\n\\\\n Data set that contains a workflow definition.\\\\n\\\\n --system-name | --sn (string)\\\\n\\\\n z/OS system to execute the workflow.\\\\n\\\\n --owner | --ow (string)\\\\n\\\\n User ID of the workflow owner. This user can perform the workflow steps or\\\\n delegate the steps to other users.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --variables-input-file | --vif (string)\\\\n\\\\n Specifies an optional properties file that you can use to pre-specify values for\\\\n one or more of the variables that are defined in the workflow definition file.\\\\n\\\\n --variables | --vs (string)\\\\n\\\\n Includes a list of variables for the workflow. The variables that you specify\\\\n here take precedence over the variables that are specified in the workflow\\\\n variable input file. Make sure the value meets all regular expression\\\\n requirements set for the corresponding variable.\\\\n\\\\n --assign-to-owner | --ato (boolean)\\\\n\\\\n Indicates whether the workflow steps are assigned to the workflow owner.\\\\n\\\\n --access-type | --at (string)\\\\n\\\\n Specifies the access type for the workflow. Public, Restricted or Private.\\\\n\\\\n Allowed values: Public, Restricted, Private\\\\n\\\\n --delete-completed | --dc (boolean)\\\\n\\\\n Whether the successfully completed jobs to be deleted from the JES spool.\\\\n\\\\n --overwrite | --ov (boolean)\\\\n\\\\n Replaces an existing workflow with a new workflow.\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using the data\\\\n set \\\\\\"TESTID.WKFLOW\\\\\\" that contains the workflow definition xml on the system\\\\n \\\\\\"TESTM1\\\\\\" with owner \\\\\\"OTHERID\\\\\\" and delete workflow with the same name if it\\\\n already exists in z/OSMF:\\\\n\\\\n $ zowe zos-workflows create workflow-from-data-set \\\\\\"testworkflow\\\\\\" --data-set \\\\\\"TESTID.WKFLOW\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"OTHERID\\\\\\" --overwrite\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using data set\\\\n \\\\\\"TESTID.WKFLOW\\\\\\" containing workflow definition xml, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and delete successfully completed jobs:\\\\n\\\\n $ zowe zos-workflows create workflow-from-data-set \\\\\\"testworkflow\\\\\\" --data-set \\\\\\"TESTID.WKFLOW\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --delete-completed\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using data set\\\\n \\\\\\"TESTID.WKFLOW\\\\\\" containing workflow definition xml, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and with variable values in the member PROPERTIES of data set\\\\n TESTID.DATA:\\\\n\\\\n $ zowe zos-workflows create workflow-from-data-set \\\\\\"testworkflow\\\\\\" --data-set \\\\\\"TESTID.WKFLOW\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --variables-input-file TESTID.DATA(PROPERTIES)\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using the data\\\\n set \\\\\\"TESTID.WKFLOW\\\\\\" that contains a workflow definition xml, on a system\\\\n \\\\\\"TESTM1\\\\\\" with owner \\\\\\"MYSYSID\\\\\\" and with the variable name DUMMYVAR and the value\\\\n DUMMYVAL. Assign it to the owner:\\\\n\\\\n $ zowe zos-workflows create workflow-from-data-set \\\\\\"testworkflow\\\\\\" --data-set \\\\\\"TESTID.WKFLOW\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --variables DUMMYVAR=DUMMYVAL --assign-to-owner\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n workflow-from-data-set | wfds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create a z/OSMF workflow on a z/OS system using a data set.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows create workflow-from-data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n workflowName\\\\t\\\\t (string)\\\\n\\\\n Name of the workflow\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --data-set | --ds (string)\\\\n\\\\n Data set that contains a workflow definition.\\\\n\\\\n --system-name | --sn (string)\\\\n\\\\n z/OS system to execute the workflow.\\\\n\\\\n --owner | --ow (string)\\\\n\\\\n User ID of the workflow owner. This user can perform the workflow steps or\\\\n delegate the steps to other users.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --variables-input-file | --vif (string)\\\\n\\\\n Specifies an optional properties file that you can use to pre-specify values for\\\\n one or more of the variables that are defined in the workflow definition file.\\\\n\\\\n --variables | --vs (string)\\\\n\\\\n Includes a list of variables for the workflow. The variables that you specify\\\\n here take precedence over the variables that are specified in the workflow\\\\n variable input file. Make sure the value meets all regular expression\\\\n requirements set for the corresponding variable.\\\\n\\\\n --assign-to-owner | --ato (boolean)\\\\n\\\\n Indicates whether the workflow steps are assigned to the workflow owner.\\\\n\\\\n --access-type | --at (string)\\\\n\\\\n Specifies the access type for the workflow. Public, Restricted or Private.\\\\n\\\\n Allowed values: Public, Restricted, Private\\\\n\\\\n --delete-completed | --dc (boolean)\\\\n\\\\n Whether the successfully completed jobs to be deleted from the JES spool.\\\\n\\\\n --overwrite | --ov (boolean)\\\\n\\\\n Replaces an existing workflow with a new workflow.\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using the data\\\\n set \\\\\\"TESTID.WKFLOW\\\\\\" that contains the workflow definition xml on the system\\\\n \\\\\\"TESTM1\\\\\\" with owner \\\\\\"OTHERID\\\\\\" and delete workflow with the same name if it\\\\n already exists in z/OSMF:\\\\n\\\\n $ zowe zos-workflows create workflow-from-data-set \\\\\\"testworkflow\\\\\\" --data-set \\\\\\"TESTID.WKFLOW\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"OTHERID\\\\\\" --overwrite\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using data set\\\\n \\\\\\"TESTID.WKFLOW\\\\\\" containing workflow definition xml, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and delete successfully completed jobs:\\\\n\\\\n $ zowe zos-workflows create workflow-from-data-set \\\\\\"testworkflow\\\\\\" --data-set \\\\\\"TESTID.WKFLOW\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --delete-completed\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using data set\\\\n \\\\\\"TESTID.WKFLOW\\\\\\" containing workflow definition xml, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and with variable values in the member PROPERTIES of data set\\\\n TESTID.DATA:\\\\n\\\\n $ zowe zos-workflows create workflow-from-data-set \\\\\\"testworkflow\\\\\\" --data-set \\\\\\"TESTID.WKFLOW\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --variables-input-file TESTID.DATA(PROPERTIES)\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using the data\\\\n set \\\\\\"TESTID.WKFLOW\\\\\\" that contains a workflow definition xml, on a system\\\\n \\\\\\"TESTM1\\\\\\" with owner \\\\\\"MYSYSID\\\\\\" and with the variable name DUMMYVAR and the value\\\\n DUMMYVAL. Assign it to the owner:\\\\n\\\\n $ zowe zos-workflows create workflow-from-data-set \\\\\\"testworkflow\\\\\\" --data-set \\\\\\"TESTID.WKFLOW\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --variables DUMMYVAR=DUMMYVAL --assign-to-owner\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n workflow-from-data-set | wfds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create a z/OSMF workflow on a z/OS system using a Data set\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows create workflow-from-data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n workflowName\\\\t\\\\t (string)\\\\n\\\\n Name of the workflow\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --data-set | --ds (string)\\\\n\\\\n Data set that contains a workflow definition.\\\\n\\\\n --system-name | --sn (string)\\\\n\\\\n z/OS system to execute the workflow.\\\\n\\\\n --owner | --ow (string)\\\\n\\\\n User ID of the workflow owner. This user can perform the workflow steps or\\\\n delegate the steps to other users.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --variables-input-file | --vif (string)\\\\n\\\\n Specifies an optional properties file that you can use to pre-specify values for\\\\n one or more of the variables that are defined in the workflow definition file.\\\\n\\\\n --variables | --vs (string)\\\\n\\\\n Includes a list of variables for the workflow. The variables that you specify\\\\n here take precedence over the variables that are specified in the workflow\\\\n variable input file. Make sure the value meets all regular expression\\\\n requirements set for the corresponding variable.\\\\n\\\\n --assign-to-owner | --ato (boolean)\\\\n\\\\n Indicates whether the workflow steps are assigned to the workflow owner.\\\\n\\\\n --access-type | --at (string)\\\\n\\\\n Specifies the access type for the workflow. Public, Restricted or Private.\\\\n\\\\n Allowed values: Public, Restricted, Private\\\\n\\\\n --delete-completed | --dc (boolean)\\\\n\\\\n Whether the successfully completed jobs to be deleted from the JES spool.\\\\n\\\\n --overwrite | --ov (boolean)\\\\n\\\\n Replaces an existing workflow with a new workflow.\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using the data\\\\n set \\\\\\"TESTID.WKFLOW\\\\\\" that contains the workflow definition xml on the system\\\\n \\\\\\"TESTM1\\\\\\" with owner \\\\\\"OTHERID\\\\\\" and delete workflow with the same name if it\\\\n already exists in z/OSMF:\\\\n\\\\n $ zowe zos-workflows create workflow-from-data-set \\\\\\"testworkflow\\\\\\" --data-set \\\\\\"TESTID.WKFLOW\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"OTHERID\\\\\\" --overwrite\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using data set\\\\n \\\\\\"TESTID.WKFLOW\\\\\\" containing workflow definition xml, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and delete successfully completed jobs:\\\\n\\\\n $ zowe zos-workflows create workflow-from-data-set \\\\\\"testworkflow\\\\\\" --data-set \\\\\\"TESTID.WKFLOW\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --delete-completed\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using data set\\\\n \\\\\\"TESTID.WKFLOW\\\\\\" containing workflow definition xml, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and with variable values in the member PROPERTIES of data set\\\\n TESTID.DATA:\\\\n\\\\n $ zowe zos-workflows create workflow-from-data-set \\\\\\"testworkflow\\\\\\" --data-set \\\\\\"TESTID.WKFLOW\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --variables-input-file TESTID.DATA(PROPERTIES)\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using the data\\\\n set \\\\\\"TESTID.WKFLOW\\\\\\" that contains a workflow definition xml, on a system\\\\n \\\\\\"TESTM1\\\\\\" with owner \\\\\\"MYSYSID\\\\\\" and with the variable name DUMMYVAR and the value\\\\n DUMMYVAL. Assign it to the owner:\\\\n\\\\n $ zowe zos-workflows create workflow-from-data-set \\\\\\"testworkflow\\\\\\" --data-set \\\\\\"TESTID.WKFLOW\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --variables DUMMYVAR=DUMMYVAL --assign-to-owner\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n workflow-from-data-set | wfds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create a z/OSMF workflow on a z/OS system using a data set.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows create workflow-from-data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n workflowName\\\\t\\\\t (string)\\\\n\\\\n Name of the workflow\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --data-set | --ds (string)\\\\n\\\\n Data set that contains a workflow definition.\\\\n\\\\n --system-name | --sn (string)\\\\n\\\\n z/OS system to execute the workflow.\\\\n\\\\n --owner | --ow (string)\\\\n\\\\n User ID of the workflow owner. This user can perform the workflow steps or\\\\n delegate the steps to other users.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --variables-input-file | --vif (string)\\\\n\\\\n Specifies an optional properties file that you can use to pre-specify values for\\\\n one or more of the variables that are defined in the workflow definition file.\\\\n\\\\n --variables | --vs (string)\\\\n\\\\n Includes a list of variables for the workflow. The variables that you specify\\\\n here take precedence over the variables that are specified in the workflow\\\\n variable input file. Make sure the value meets all regular expression\\\\n requirements set for the corresponding variable.\\\\n\\\\n --assign-to-owner | --ato (boolean)\\\\n\\\\n Indicates whether the workflow steps are assigned to the workflow owner.\\\\n\\\\n --access-type | --at (string)\\\\n\\\\n Specifies the access type for the workflow. Public, Restricted or Private.\\\\n\\\\n Allowed values: Public, Restricted, Private\\\\n\\\\n --delete-completed | --dc (boolean)\\\\n\\\\n Whether the successfully completed jobs to be deleted from the JES spool.\\\\n\\\\n --overwrite | --ov (boolean)\\\\n\\\\n Replaces an existing workflow with a new workflow.\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using the data\\\\n set \\\\\\"TESTID.WKFLOW\\\\\\" that contains the workflow definition xml on the system\\\\n \\\\\\"TESTM1\\\\\\" with owner \\\\\\"OTHERID\\\\\\" and delete workflow with the same name if it\\\\n already exists in z/OSMF:\\\\n\\\\n $ zowe zos-workflows create workflow-from-data-set \\\\\\"testworkflow\\\\\\" --data-set \\\\\\"TESTID.WKFLOW\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"OTHERID\\\\\\" --overwrite\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using data set\\\\n \\\\\\"TESTID.WKFLOW\\\\\\" containing workflow definition xml, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and delete successfully completed jobs:\\\\n\\\\n $ zowe zos-workflows create workflow-from-data-set \\\\\\"testworkflow\\\\\\" --data-set \\\\\\"TESTID.WKFLOW\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --delete-completed\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using data set\\\\n \\\\\\"TESTID.WKFLOW\\\\\\" containing workflow definition xml, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and with variable values in the member PROPERTIES of data set\\\\n TESTID.DATA:\\\\n\\\\n $ zowe zos-workflows create workflow-from-data-set \\\\\\"testworkflow\\\\\\" --data-set \\\\\\"TESTID.WKFLOW\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --variables-input-file TESTID.DATA(PROPERTIES)\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using the data\\\\n set \\\\\\"TESTID.WKFLOW\\\\\\" that contains a workflow definition xml, on a system\\\\n \\\\\\"TESTM1\\\\\\" with owner \\\\\\"MYSYSID\\\\\\" and with the variable name DUMMYVAR and the value\\\\n DUMMYVAL. Assign it to the owner:\\\\n\\\\n $ zowe zos-workflows create workflow-from-data-set \\\\\\"testworkflow\\\\\\" --data-set \\\\\\"TESTID.WKFLOW\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --variables DUMMYVAR=DUMMYVAL --assign-to-owner\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/workflows/__integration__/create/localfile/__snapshots__/cli.workflows.create.workflowLocalFile.integration.test.ts.snap b/packages/cli/__tests__/workflows/__integration__/create/localfile/__snapshots__/cli.workflows.create.workflowLocalFile.integration.test.ts.snap index d811525410..5b38bbe454 100644 --- a/packages/cli/__tests__/workflows/__integration__/create/localfile/__snapshots__/cli.workflows.create.workflowLocalFile.integration.test.ts.snap +++ b/packages/cli/__tests__/workflows/__integration__/create/localfile/__snapshots__/cli.workflows.create.workflowLocalFile.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Create workflow with local file integration test should display create DESCRIPTION ----------- - Create a z/OSMF workflow on a z/OS system using a Local file + Create a z/OSMF workflow on a z/OS system using a local file. USAGE ----- @@ -76,8 +76,8 @@ exports[`Create workflow with local file integration test should display create --remote-directory | --rd (string) - The remote uss directory where the files are to be uploaded. The directory has - to exist + The remote USS directory where the files are to be uploaded. The directory has + to exist. --keep-files | --kf (boolean) @@ -227,8 +227,8 @@ exports[`Create workflow with local file integration test should display create \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: workflow-from-local-file.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n workflow-from-local-file | wflf\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create a z/OSMF workflow on a z/OS system using a Local file\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows create workflow-from-local-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n workflowName\\\\t\\\\t (string)\\\\n\\\\n Name of the workflow\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --local-file | --lf (string)\\\\n\\\\n Local file that contains workflow definition.\\\\n\\\\n --system-name | --sn (string)\\\\n\\\\n z/OS system to execute the workflow.\\\\n\\\\n --owner | --ow (string)\\\\n\\\\n User ID of the workflow owner. This user can perform the workflow steps or\\\\n delegate the steps to other users.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --variables-input-file | --vif (string)\\\\n\\\\n Specifies an optional properties file that you can use to pre-specify values for\\\\n one or more of the variables that are defined in the workflow definition file.\\\\n\\\\n --variables | --vs (string)\\\\n\\\\n Includes a list of variables for the workflow. The variables that you specify\\\\n here take precedence over the variables that are specified in the workflow\\\\n variable input file. Make sure the value meets all regular expression\\\\n requirements set for the corresponding variable.\\\\n\\\\n --assign-to-owner | --ato (boolean)\\\\n\\\\n Indicates whether the workflow steps are assigned to the workflow owner.\\\\n\\\\n --access-type | --at (string)\\\\n\\\\n Specifies the access type for the workflow. Public, Restricted or Private.\\\\n\\\\n Allowed values: Public, Restricted, Private\\\\n\\\\n --delete-completed | --dc (boolean)\\\\n\\\\n Whether the successfully completed jobs to be deleted from the JES spool.\\\\n\\\\n --overwrite | --ov (boolean)\\\\n\\\\n Replaces an existing workflow with a new workflow.\\\\n\\\\n --remote-directory | --rd (string)\\\\n\\\\n The remote uss directory where the files are to be uploaded. The directory has\\\\n to exist\\\\n\\\\n --keep-files | --kf (boolean)\\\\n\\\\n Avoid deletion the uploaded files in /tmp or another specified directory after\\\\n successful execution.\\\\n\\\\n Default value: false\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using the local\\\\n file \\\\\\"TESTID_WKFLOW.xml\\\\\\" that contains the workflow definition xml on the system\\\\n \\\\\\"TESTM1\\\\\\" with owner \\\\\\"OTHERID\\\\\\" and delete workflow with the same name if it\\\\n already exists in z/OSMF:\\\\n\\\\n $ zowe zos-workflows create workflow-from-local-file \\\\\\"testworkflow\\\\\\" --local-file \\\\\\"TESTID_WKFLOW.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"OTHERID\\\\\\" --overwrite\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n workflow-from-local-file | wflf\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create a z/OSMF workflow on a z/OS system using a local file.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows create workflow-from-local-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n workflowName\\\\t\\\\t (string)\\\\n\\\\n Name of the workflow\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --local-file | --lf (string)\\\\n\\\\n Local file that contains workflow definition.\\\\n\\\\n --system-name | --sn (string)\\\\n\\\\n z/OS system to execute the workflow.\\\\n\\\\n --owner | --ow (string)\\\\n\\\\n User ID of the workflow owner. This user can perform the workflow steps or\\\\n delegate the steps to other users.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --variables-input-file | --vif (string)\\\\n\\\\n Specifies an optional properties file that you can use to pre-specify values for\\\\n one or more of the variables that are defined in the workflow definition file.\\\\n\\\\n --variables | --vs (string)\\\\n\\\\n Includes a list of variables for the workflow. The variables that you specify\\\\n here take precedence over the variables that are specified in the workflow\\\\n variable input file. Make sure the value meets all regular expression\\\\n requirements set for the corresponding variable.\\\\n\\\\n --assign-to-owner | --ato (boolean)\\\\n\\\\n Indicates whether the workflow steps are assigned to the workflow owner.\\\\n\\\\n --access-type | --at (string)\\\\n\\\\n Specifies the access type for the workflow. Public, Restricted or Private.\\\\n\\\\n Allowed values: Public, Restricted, Private\\\\n\\\\n --delete-completed | --dc (boolean)\\\\n\\\\n Whether the successfully completed jobs to be deleted from the JES spool.\\\\n\\\\n --overwrite | --ov (boolean)\\\\n\\\\n Replaces an existing workflow with a new workflow.\\\\n\\\\n --remote-directory | --rd (string)\\\\n\\\\n The remote USS directory where the files are to be uploaded. The directory has\\\\n to exist.\\\\n\\\\n --keep-files | --kf (boolean)\\\\n\\\\n Avoid deletion the uploaded files in /tmp or another specified directory after\\\\n successful execution.\\\\n\\\\n Default value: false\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using the local\\\\n file \\\\\\"TESTID_WKFLOW.xml\\\\\\" that contains the workflow definition xml on the system\\\\n \\\\\\"TESTM1\\\\\\" with owner \\\\\\"OTHERID\\\\\\" and delete workflow with the same name if it\\\\n already exists in z/OSMF:\\\\n\\\\n $ zowe zos-workflows create workflow-from-local-file \\\\\\"testworkflow\\\\\\" --local-file \\\\\\"TESTID_WKFLOW.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"OTHERID\\\\\\" --overwrite\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n workflow-from-local-file | wflf\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create a z/OSMF workflow on a z/OS system using a Local file\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows create workflow-from-local-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n workflowName\\\\t\\\\t (string)\\\\n\\\\n Name of the workflow\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --local-file | --lf (string)\\\\n\\\\n Local file that contains workflow definition.\\\\n\\\\n --system-name | --sn (string)\\\\n\\\\n z/OS system to execute the workflow.\\\\n\\\\n --owner | --ow (string)\\\\n\\\\n User ID of the workflow owner. This user can perform the workflow steps or\\\\n delegate the steps to other users.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --variables-input-file | --vif (string)\\\\n\\\\n Specifies an optional properties file that you can use to pre-specify values for\\\\n one or more of the variables that are defined in the workflow definition file.\\\\n\\\\n --variables | --vs (string)\\\\n\\\\n Includes a list of variables for the workflow. The variables that you specify\\\\n here take precedence over the variables that are specified in the workflow\\\\n variable input file. Make sure the value meets all regular expression\\\\n requirements set for the corresponding variable.\\\\n\\\\n --assign-to-owner | --ato (boolean)\\\\n\\\\n Indicates whether the workflow steps are assigned to the workflow owner.\\\\n\\\\n --access-type | --at (string)\\\\n\\\\n Specifies the access type for the workflow. Public, Restricted or Private.\\\\n\\\\n Allowed values: Public, Restricted, Private\\\\n\\\\n --delete-completed | --dc (boolean)\\\\n\\\\n Whether the successfully completed jobs to be deleted from the JES spool.\\\\n\\\\n --overwrite | --ov (boolean)\\\\n\\\\n Replaces an existing workflow with a new workflow.\\\\n\\\\n --remote-directory | --rd (string)\\\\n\\\\n The remote uss directory where the files are to be uploaded. The directory has\\\\n to exist\\\\n\\\\n --keep-files | --kf (boolean)\\\\n\\\\n Avoid deletion the uploaded files in /tmp or another specified directory after\\\\n successful execution.\\\\n\\\\n Default value: false\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using the local\\\\n file \\\\\\"TESTID_WKFLOW.xml\\\\\\" that contains the workflow definition xml on the system\\\\n \\\\\\"TESTM1\\\\\\" with owner \\\\\\"OTHERID\\\\\\" and delete workflow with the same name if it\\\\n already exists in z/OSMF:\\\\n\\\\n $ zowe zos-workflows create workflow-from-local-file \\\\\\"testworkflow\\\\\\" --local-file \\\\\\"TESTID_WKFLOW.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"OTHERID\\\\\\" --overwrite\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n workflow-from-local-file | wflf\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create a z/OSMF workflow on a z/OS system using a local file.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows create workflow-from-local-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n workflowName\\\\t\\\\t (string)\\\\n\\\\n Name of the workflow\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --local-file | --lf (string)\\\\n\\\\n Local file that contains workflow definition.\\\\n\\\\n --system-name | --sn (string)\\\\n\\\\n z/OS system to execute the workflow.\\\\n\\\\n --owner | --ow (string)\\\\n\\\\n User ID of the workflow owner. This user can perform the workflow steps or\\\\n delegate the steps to other users.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --variables-input-file | --vif (string)\\\\n\\\\n Specifies an optional properties file that you can use to pre-specify values for\\\\n one or more of the variables that are defined in the workflow definition file.\\\\n\\\\n --variables | --vs (string)\\\\n\\\\n Includes a list of variables for the workflow. The variables that you specify\\\\n here take precedence over the variables that are specified in the workflow\\\\n variable input file. Make sure the value meets all regular expression\\\\n requirements set for the corresponding variable.\\\\n\\\\n --assign-to-owner | --ato (boolean)\\\\n\\\\n Indicates whether the workflow steps are assigned to the workflow owner.\\\\n\\\\n --access-type | --at (string)\\\\n\\\\n Specifies the access type for the workflow. Public, Restricted or Private.\\\\n\\\\n Allowed values: Public, Restricted, Private\\\\n\\\\n --delete-completed | --dc (boolean)\\\\n\\\\n Whether the successfully completed jobs to be deleted from the JES spool.\\\\n\\\\n --overwrite | --ov (boolean)\\\\n\\\\n Replaces an existing workflow with a new workflow.\\\\n\\\\n --remote-directory | --rd (string)\\\\n\\\\n The remote USS directory where the files are to be uploaded. The directory has\\\\n to exist.\\\\n\\\\n --keep-files | --kf (boolean)\\\\n\\\\n Avoid deletion the uploaded files in /tmp or another specified directory after\\\\n successful execution.\\\\n\\\\n Default value: false\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using the local\\\\n file \\\\\\"TESTID_WKFLOW.xml\\\\\\" that contains the workflow definition xml on the system\\\\n \\\\\\"TESTM1\\\\\\" with owner \\\\\\"OTHERID\\\\\\" and delete workflow with the same name if it\\\\n already exists in z/OSMF:\\\\n\\\\n $ zowe zos-workflows create workflow-from-local-file \\\\\\"testworkflow\\\\\\" --local-file \\\\\\"TESTID_WKFLOW.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"OTHERID\\\\\\" --overwrite\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/workflows/__integration__/create/ussfile/__snapshots__/cli.workflows.create.workflowUss.integration.test.ts.snap b/packages/cli/__tests__/workflows/__integration__/create/ussfile/__snapshots__/cli.workflows.create.workflowUss.integration.test.ts.snap index 016a59a445..356ddfe86a 100644 --- a/packages/cli/__tests__/workflows/__integration__/create/ussfile/__snapshots__/cli.workflows.create.workflowUss.integration.test.ts.snap +++ b/packages/cli/__tests__/workflows/__integration__/create/ussfile/__snapshots__/cli.workflows.create.workflowUss.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Create workflow with uss file integration test should display create wo DESCRIPTION ----------- - Create a workflow instance in z/OSMF using a USS file + Create a workflow instance in z/OSMF using a USS file. USAGE ----- @@ -30,7 +30,7 @@ exports[`Create workflow with uss file integration test should display create wo --uss-file | --uf (string) - Uss file that contains workflow definition. + USS file that contains workflow definition. --system-name | --sn (string) @@ -235,8 +235,8 @@ exports[`Create workflow with uss file integration test should display create wo \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: workflow-from-uss-file.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n workflow-from-uss-file | wfuf\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create a workflow instance in z/OSMF using a USS file\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows create workflow-from-uss-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n workflowName\\\\t\\\\t (string)\\\\n\\\\n Name of the workflow instance to create\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --uss-file | --uf (string)\\\\n\\\\n Uss file that contains workflow definition.\\\\n\\\\n --system-name | --sn (string)\\\\n\\\\n z/OS system to execute the workflow.\\\\n\\\\n --owner | --ow (string)\\\\n\\\\n User ID of the workflow owner. This user can perform the workflow steps or\\\\n delegate the steps to other users.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --variables-input-file | --vif (string)\\\\n\\\\n Specifies an optional properties file that you can use to pre-specify values for\\\\n one or more of the variables that are defined in the workflow definition file.\\\\n\\\\n --variables | --vs (string)\\\\n\\\\n Includes a list of variables for the workflow. The variables that you specify\\\\n here take precedence over the variables that are specified in the workflow\\\\n variable input file. Make sure the value meets all regular expression\\\\n requirements set for the corresponding variable.\\\\n\\\\n --assign-to-owner | --ato (boolean)\\\\n\\\\n Indicates whether the workflow steps are assigned to the workflow owner.\\\\n\\\\n --access-type | --at (string)\\\\n\\\\n Specifies the access type for the workflow. Public, Restricted or Private.\\\\n\\\\n Allowed values: Public, Restricted, Private\\\\n\\\\n --delete-completed | --dc (boolean)\\\\n\\\\n Whether the successfully completed jobs to be deleted from the JES spool.\\\\n\\\\n --overwrite | --ov (boolean)\\\\n\\\\n Replaces an existing workflow with a new workflow.\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using uss file\\\\n \\\\\\"/path/workflow.xml\\\\\\" containing workflow definition, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"OTHERID\\\\\\" and delete workflow with the same name if it already exists in\\\\n z/OSMF:\\\\n\\\\n $ zowe zos-workflows create workflow-from-uss-file \\\\\\"testworkflow\\\\\\" --uss-file \\\\\\"/path/workflow.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"OTHERID\\\\\\" --overwrite\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using uss file\\\\n \\\\\\"/path/workflow.xml\\\\\\" containing workflow definition, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and delete successfully completed jobs:\\\\n\\\\n $ zowe zos-workflows create workflow-from-uss-file \\\\\\"testworkflow\\\\\\" --uss-file \\\\\\"/path/workflow.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --delete-completed\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using uss file\\\\n \\\\\\"/path/workflow.xml\\\\\\" containing workflow definition, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and with variable values in the member PROPERTIES of data set\\\\n TESTID.DATA:\\\\n\\\\n $ zowe zos-workflows create workflow-from-uss-file \\\\\\"testworkflow\\\\\\" --uss-file \\\\\\"/path/workflow.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --variables-input-file TESTID.DATA(PROPERTIES)\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using uss file\\\\n \\\\\\"/path/workflow.xml\\\\\\" containing workflow definition, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and with variables VAR1 and VAR2 with values DUMMYVAL1 and\\\\n DUMMYVAL2, and assign it to the owner:\\\\n\\\\n $ zowe zos-workflows create workflow-from-uss-file \\\\\\"testworkflow\\\\\\" --uss-file \\\\\\"/path/workflow.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\"--variables VAR1=DUMMYVAL1,VAR2=DUMMYVAL2 --owner \\\\\\"MYSYSID\\\\\\" --assign-to-owner\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n workflow-from-uss-file | wfuf\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create a workflow instance in z/OSMF using a USS file.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows create workflow-from-uss-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n workflowName\\\\t\\\\t (string)\\\\n\\\\n Name of the workflow instance to create\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --uss-file | --uf (string)\\\\n\\\\n USS file that contains workflow definition.\\\\n\\\\n --system-name | --sn (string)\\\\n\\\\n z/OS system to execute the workflow.\\\\n\\\\n --owner | --ow (string)\\\\n\\\\n User ID of the workflow owner. This user can perform the workflow steps or\\\\n delegate the steps to other users.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --variables-input-file | --vif (string)\\\\n\\\\n Specifies an optional properties file that you can use to pre-specify values for\\\\n one or more of the variables that are defined in the workflow definition file.\\\\n\\\\n --variables | --vs (string)\\\\n\\\\n Includes a list of variables for the workflow. The variables that you specify\\\\n here take precedence over the variables that are specified in the workflow\\\\n variable input file. Make sure the value meets all regular expression\\\\n requirements set for the corresponding variable.\\\\n\\\\n --assign-to-owner | --ato (boolean)\\\\n\\\\n Indicates whether the workflow steps are assigned to the workflow owner.\\\\n\\\\n --access-type | --at (string)\\\\n\\\\n Specifies the access type for the workflow. Public, Restricted or Private.\\\\n\\\\n Allowed values: Public, Restricted, Private\\\\n\\\\n --delete-completed | --dc (boolean)\\\\n\\\\n Whether the successfully completed jobs to be deleted from the JES spool.\\\\n\\\\n --overwrite | --ov (boolean)\\\\n\\\\n Replaces an existing workflow with a new workflow.\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using uss file\\\\n \\\\\\"/path/workflow.xml\\\\\\" containing workflow definition, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"OTHERID\\\\\\" and delete workflow with the same name if it already exists in\\\\n z/OSMF:\\\\n\\\\n $ zowe zos-workflows create workflow-from-uss-file \\\\\\"testworkflow\\\\\\" --uss-file \\\\\\"/path/workflow.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"OTHERID\\\\\\" --overwrite\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using uss file\\\\n \\\\\\"/path/workflow.xml\\\\\\" containing workflow definition, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and delete successfully completed jobs:\\\\n\\\\n $ zowe zos-workflows create workflow-from-uss-file \\\\\\"testworkflow\\\\\\" --uss-file \\\\\\"/path/workflow.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --delete-completed\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using uss file\\\\n \\\\\\"/path/workflow.xml\\\\\\" containing workflow definition, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and with variable values in the member PROPERTIES of data set\\\\n TESTID.DATA:\\\\n\\\\n $ zowe zos-workflows create workflow-from-uss-file \\\\\\"testworkflow\\\\\\" --uss-file \\\\\\"/path/workflow.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --variables-input-file TESTID.DATA(PROPERTIES)\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using uss file\\\\n \\\\\\"/path/workflow.xml\\\\\\" containing workflow definition, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and with variables VAR1 and VAR2 with values DUMMYVAL1 and\\\\n DUMMYVAL2, and assign it to the owner:\\\\n\\\\n $ zowe zos-workflows create workflow-from-uss-file \\\\\\"testworkflow\\\\\\" --uss-file \\\\\\"/path/workflow.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\"--variables VAR1=DUMMYVAL1,VAR2=DUMMYVAL2 --owner \\\\\\"MYSYSID\\\\\\" --assign-to-owner\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n workflow-from-uss-file | wfuf\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create a workflow instance in z/OSMF using a USS file\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows create workflow-from-uss-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n workflowName\\\\t\\\\t (string)\\\\n\\\\n Name of the workflow instance to create\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --uss-file | --uf (string)\\\\n\\\\n Uss file that contains workflow definition.\\\\n\\\\n --system-name | --sn (string)\\\\n\\\\n z/OS system to execute the workflow.\\\\n\\\\n --owner | --ow (string)\\\\n\\\\n User ID of the workflow owner. This user can perform the workflow steps or\\\\n delegate the steps to other users.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --variables-input-file | --vif (string)\\\\n\\\\n Specifies an optional properties file that you can use to pre-specify values for\\\\n one or more of the variables that are defined in the workflow definition file.\\\\n\\\\n --variables | --vs (string)\\\\n\\\\n Includes a list of variables for the workflow. The variables that you specify\\\\n here take precedence over the variables that are specified in the workflow\\\\n variable input file. Make sure the value meets all regular expression\\\\n requirements set for the corresponding variable.\\\\n\\\\n --assign-to-owner | --ato (boolean)\\\\n\\\\n Indicates whether the workflow steps are assigned to the workflow owner.\\\\n\\\\n --access-type | --at (string)\\\\n\\\\n Specifies the access type for the workflow. Public, Restricted or Private.\\\\n\\\\n Allowed values: Public, Restricted, Private\\\\n\\\\n --delete-completed | --dc (boolean)\\\\n\\\\n Whether the successfully completed jobs to be deleted from the JES spool.\\\\n\\\\n --overwrite | --ov (boolean)\\\\n\\\\n Replaces an existing workflow with a new workflow.\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using uss file\\\\n \\\\\\"/path/workflow.xml\\\\\\" containing workflow definition, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"OTHERID\\\\\\" and delete workflow with the same name if it already exists in\\\\n z/OSMF:\\\\n\\\\n $ zowe zos-workflows create workflow-from-uss-file \\\\\\"testworkflow\\\\\\" --uss-file \\\\\\"/path/workflow.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"OTHERID\\\\\\" --overwrite\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using uss file\\\\n \\\\\\"/path/workflow.xml\\\\\\" containing workflow definition, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and delete successfully completed jobs:\\\\n\\\\n $ zowe zos-workflows create workflow-from-uss-file \\\\\\"testworkflow\\\\\\" --uss-file \\\\\\"/path/workflow.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --delete-completed\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using uss file\\\\n \\\\\\"/path/workflow.xml\\\\\\" containing workflow definition, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and with variable values in the member PROPERTIES of data set\\\\n TESTID.DATA:\\\\n\\\\n $ zowe zos-workflows create workflow-from-uss-file \\\\\\"testworkflow\\\\\\" --uss-file \\\\\\"/path/workflow.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --variables-input-file TESTID.DATA(PROPERTIES)\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using uss file\\\\n \\\\\\"/path/workflow.xml\\\\\\" containing workflow definition, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and with variables VAR1 and VAR2 with values DUMMYVAL1 and\\\\n DUMMYVAL2, and assign it to the owner:\\\\n\\\\n $ zowe zos-workflows create workflow-from-uss-file \\\\\\"testworkflow\\\\\\" --uss-file \\\\\\"/path/workflow.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\"--variables VAR1=DUMMYVAL1,VAR2=DUMMYVAL2 --owner \\\\\\"MYSYSID\\\\\\" --assign-to-owner\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n workflow-from-uss-file | wfuf\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create a workflow instance in z/OSMF using a USS file.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows create workflow-from-uss-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n workflowName\\\\t\\\\t (string)\\\\n\\\\n Name of the workflow instance to create\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --uss-file | --uf (string)\\\\n\\\\n USS file that contains workflow definition.\\\\n\\\\n --system-name | --sn (string)\\\\n\\\\n z/OS system to execute the workflow.\\\\n\\\\n --owner | --ow (string)\\\\n\\\\n User ID of the workflow owner. This user can perform the workflow steps or\\\\n delegate the steps to other users.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --variables-input-file | --vif (string)\\\\n\\\\n Specifies an optional properties file that you can use to pre-specify values for\\\\n one or more of the variables that are defined in the workflow definition file.\\\\n\\\\n --variables | --vs (string)\\\\n\\\\n Includes a list of variables for the workflow. The variables that you specify\\\\n here take precedence over the variables that are specified in the workflow\\\\n variable input file. Make sure the value meets all regular expression\\\\n requirements set for the corresponding variable.\\\\n\\\\n --assign-to-owner | --ato (boolean)\\\\n\\\\n Indicates whether the workflow steps are assigned to the workflow owner.\\\\n\\\\n --access-type | --at (string)\\\\n\\\\n Specifies the access type for the workflow. Public, Restricted or Private.\\\\n\\\\n Allowed values: Public, Restricted, Private\\\\n\\\\n --delete-completed | --dc (boolean)\\\\n\\\\n Whether the successfully completed jobs to be deleted from the JES spool.\\\\n\\\\n --overwrite | --ov (boolean)\\\\n\\\\n Replaces an existing workflow with a new workflow.\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using uss file\\\\n \\\\\\"/path/workflow.xml\\\\\\" containing workflow definition, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"OTHERID\\\\\\" and delete workflow with the same name if it already exists in\\\\n z/OSMF:\\\\n\\\\n $ zowe zos-workflows create workflow-from-uss-file \\\\\\"testworkflow\\\\\\" --uss-file \\\\\\"/path/workflow.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"OTHERID\\\\\\" --overwrite\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using uss file\\\\n \\\\\\"/path/workflow.xml\\\\\\" containing workflow definition, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and delete successfully completed jobs:\\\\n\\\\n $ zowe zos-workflows create workflow-from-uss-file \\\\\\"testworkflow\\\\\\" --uss-file \\\\\\"/path/workflow.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --delete-completed\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using uss file\\\\n \\\\\\"/path/workflow.xml\\\\\\" containing workflow definition, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and with variable values in the member PROPERTIES of data set\\\\n TESTID.DATA:\\\\n\\\\n $ zowe zos-workflows create workflow-from-uss-file \\\\\\"testworkflow\\\\\\" --uss-file \\\\\\"/path/workflow.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\" --owner \\\\\\"MYSYSID\\\\\\" --variables-input-file TESTID.DATA(PROPERTIES)\\\\n\\\\n - Create a workflow with name \\\\\\"testworkflow\\\\\\" using uss file\\\\n \\\\\\"/path/workflow.xml\\\\\\" containing workflow definition, on system \\\\\\"TESTM1\\\\\\" with\\\\n owner \\\\\\"MYSYSID\\\\\\" and with variables VAR1 and VAR2 with values DUMMYVAL1 and\\\\n DUMMYVAL2, and assign it to the owner:\\\\n\\\\n $ zowe zos-workflows create workflow-from-uss-file \\\\\\"testworkflow\\\\\\" --uss-file \\\\\\"/path/workflow.xml\\\\\\" --system-name \\\\\\"TESTM1\\\\\\"--variables VAR1=DUMMYVAL1,VAR2=DUMMYVAL2 --owner \\\\\\"MYSYSID\\\\\\" --assign-to-owner\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/workflows/__integration__/delete/activeWorkflow/__snapshots__/cli.workflows.delete.activeworkflow.integration.test.ts.snap b/packages/cli/__tests__/workflows/__integration__/delete/activeWorkflow/__snapshots__/cli.workflows.delete.activeworkflow.integration.test.ts.snap index 45394408f3..51b85d298c 100644 --- a/packages/cli/__tests__/workflows/__integration__/delete/activeWorkflow/__snapshots__/cli.workflows.delete.activeworkflow.integration.test.ts.snap +++ b/packages/cli/__tests__/workflows/__integration__/delete/activeWorkflow/__snapshots__/cli.workflows.delete.activeworkflow.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Delete active workflow integration test should display delete workflow DESCRIPTION ----------- - Delete an active workflow instance in z/OSMF + Delete an active workflow instance in z/OSMF. USAGE ----- @@ -142,8 +142,8 @@ exports[`Delete active workflow integration test should display delete workflow \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: active-workflow.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n active-workflow | aw\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete an active workflow instance in z/OSMF\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows delete active-workflow [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --workflow-key | --wk (string)\\\\n\\\\n Delete active workflow by specified workflow key\\\\n\\\\n --workflow-name | --wn (string)\\\\n\\\\n Delete active workflow by specified workflow name\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - To delete a workflow instance in z/OSMF with workflow key\\\\n \\\\\\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete active-workflow --workflow-key \\\\\\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\\\\\"\\\\n\\\\n - To delete a workflow instance in z/OSMF with workflow name\\\\n \\\\\\"testWorkflow\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete active-workflow --workflow-name \\\\\\"testWorkflow\\\\\\"\\\\n\\\\n - To delete multiple workflow instances in z/OSMF with names\\\\n starting with \\\\\\"test\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete active-workflow --workflow-name \\\\\\"test.*\\\\\\"\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n active-workflow | aw\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete an active workflow instance in z/OSMF.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows delete active-workflow [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --workflow-key | --wk (string)\\\\n\\\\n Delete active workflow by specified workflow key\\\\n\\\\n --workflow-name | --wn (string)\\\\n\\\\n Delete active workflow by specified workflow name\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - To delete a workflow instance in z/OSMF with workflow key\\\\n \\\\\\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete active-workflow --workflow-key \\\\\\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\\\\\"\\\\n\\\\n - To delete a workflow instance in z/OSMF with workflow name\\\\n \\\\\\"testWorkflow\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete active-workflow --workflow-name \\\\\\"testWorkflow\\\\\\"\\\\n\\\\n - To delete multiple workflow instances in z/OSMF with names\\\\n starting with \\\\\\"test\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete active-workflow --workflow-name \\\\\\"test.*\\\\\\"\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n active-workflow | aw\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete an active workflow instance in z/OSMF\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows delete active-workflow [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --workflow-key | --wk (string)\\\\n\\\\n Delete active workflow by specified workflow key\\\\n\\\\n --workflow-name | --wn (string)\\\\n\\\\n Delete active workflow by specified workflow name\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - To delete a workflow instance in z/OSMF with workflow key\\\\n \\\\\\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete active-workflow --workflow-key \\\\\\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\\\\\"\\\\n\\\\n - To delete a workflow instance in z/OSMF with workflow name\\\\n \\\\\\"testWorkflow\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete active-workflow --workflow-name \\\\\\"testWorkflow\\\\\\"\\\\n\\\\n - To delete multiple workflow instances in z/OSMF with names\\\\n starting with \\\\\\"test\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete active-workflow --workflow-name \\\\\\"test.*\\\\\\"\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n active-workflow | aw\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete an active workflow instance in z/OSMF.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows delete active-workflow [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --workflow-key | --wk (string)\\\\n\\\\n Delete active workflow by specified workflow key\\\\n\\\\n --workflow-name | --wn (string)\\\\n\\\\n Delete active workflow by specified workflow name\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - To delete a workflow instance in z/OSMF with workflow key\\\\n \\\\\\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete active-workflow --workflow-key \\\\\\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\\\\\"\\\\n\\\\n - To delete a workflow instance in z/OSMF with workflow name\\\\n \\\\\\"testWorkflow\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete active-workflow --workflow-name \\\\\\"testWorkflow\\\\\\"\\\\n\\\\n - To delete multiple workflow instances in z/OSMF with names\\\\n starting with \\\\\\"test\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete active-workflow --workflow-name \\\\\\"test.*\\\\\\"\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/workflows/__integration__/delete/archivedWorkflow/__snapshots__/cli.workflows.delete.archivedworkflow.integration.test.ts.snap b/packages/cli/__tests__/workflows/__integration__/delete/archivedWorkflow/__snapshots__/cli.workflows.delete.archivedworkflow.integration.test.ts.snap index a0929a54b2..8694b16276 100644 --- a/packages/cli/__tests__/workflows/__integration__/delete/archivedWorkflow/__snapshots__/cli.workflows.delete.archivedworkflow.integration.test.ts.snap +++ b/packages/cli/__tests__/workflows/__integration__/delete/archivedWorkflow/__snapshots__/cli.workflows.delete.archivedworkflow.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Delete archived workflow integration test should display delete workflo DESCRIPTION ----------- - Delete an archived workflow from z/OSMF + Delete an archived workflow from z/OSMF. USAGE ----- @@ -142,8 +142,8 @@ exports[`Delete archived workflow integration test should display delete workflo \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: archived-workflow.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n archived-workflow | arw\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete an archived workflow from z/OSMF\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows delete archived-workflow [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --workflow-key | --wk (string)\\\\n\\\\n Delete an archived workflow by specified workflow key\\\\n\\\\n --workflow-name | --wn (string)\\\\n\\\\n Delete an archived workflow by specified workflow name\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - To delete an archived workflow from z/OSMF with workflow\\\\n key \\\\\\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete archived-workflow --workflow-key \\\\\\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\\\\\"\\\\n\\\\n - To delete an archived workflow from z/OSMF with workflow\\\\n name \\\\\\"testWorkflow\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete archived-workflow --workflow-name \\\\\\"testWorkflow\\\\\\"\\\\n\\\\n - To delete multiple archived workflows from z/OSMF with\\\\n names beginnig with \\\\\\"test\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete archived-workflow --workflow-name \\\\\\"test.*\\\\\\"\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n archived-workflow | arw\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete an archived workflow from z/OSMF.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows delete archived-workflow [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --workflow-key | --wk (string)\\\\n\\\\n Delete an archived workflow by specified workflow key\\\\n\\\\n --workflow-name | --wn (string)\\\\n\\\\n Delete an archived workflow by specified workflow name\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - To delete an archived workflow from z/OSMF with workflow\\\\n key \\\\\\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete archived-workflow --workflow-key \\\\\\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\\\\\"\\\\n\\\\n - To delete an archived workflow from z/OSMF with workflow\\\\n name \\\\\\"testWorkflow\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete archived-workflow --workflow-name \\\\\\"testWorkflow\\\\\\"\\\\n\\\\n - To delete multiple archived workflows from z/OSMF with\\\\n names beginnig with \\\\\\"test\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete archived-workflow --workflow-name \\\\\\"test.*\\\\\\"\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n archived-workflow | arw\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete an archived workflow from z/OSMF\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows delete archived-workflow [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --workflow-key | --wk (string)\\\\n\\\\n Delete an archived workflow by specified workflow key\\\\n\\\\n --workflow-name | --wn (string)\\\\n\\\\n Delete an archived workflow by specified workflow name\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - To delete an archived workflow from z/OSMF with workflow\\\\n key \\\\\\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete archived-workflow --workflow-key \\\\\\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\\\\\"\\\\n\\\\n - To delete an archived workflow from z/OSMF with workflow\\\\n name \\\\\\"testWorkflow\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete archived-workflow --workflow-name \\\\\\"testWorkflow\\\\\\"\\\\n\\\\n - To delete multiple archived workflows from z/OSMF with\\\\n names beginnig with \\\\\\"test\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete archived-workflow --workflow-name \\\\\\"test.*\\\\\\"\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n archived-workflow | arw\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete an archived workflow from z/OSMF.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows delete archived-workflow [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --workflow-key | --wk (string)\\\\n\\\\n Delete an archived workflow by specified workflow key\\\\n\\\\n --workflow-name | --wn (string)\\\\n\\\\n Delete an archived workflow by specified workflow name\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - To delete an archived workflow from z/OSMF with workflow\\\\n key \\\\\\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete archived-workflow --workflow-key \\\\\\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\\\\\"\\\\n\\\\n - To delete an archived workflow from z/OSMF with workflow\\\\n name \\\\\\"testWorkflow\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete archived-workflow --workflow-name \\\\\\"testWorkflow\\\\\\"\\\\n\\\\n - To delete multiple archived workflows from z/OSMF with\\\\n names beginnig with \\\\\\"test\\\\\\":\\\\n\\\\n $ zowe zos-workflows delete archived-workflow --workflow-name \\\\\\"test.*\\\\\\"\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/workflows/__integration__/list/activeWorkflowDetails/__snapshots__/cli.workflows.list.activeWorkflowDetails.integration.test.ts.snap b/packages/cli/__tests__/workflows/__integration__/list/activeWorkflowDetails/__snapshots__/cli.workflows.list.activeWorkflowDetails.integration.test.ts.snap index 0da8a17c9d..5aef25f392 100644 --- a/packages/cli/__tests__/workflows/__integration__/list/activeWorkflowDetails/__snapshots__/cli.workflows.list.activeWorkflowDetails.integration.test.ts.snap +++ b/packages/cli/__tests__/workflows/__integration__/list/activeWorkflowDetails/__snapshots__/cli.workflows.list.activeWorkflowDetails.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`List Active Workflow Details should display the help 1`] = ` DESCRIPTION ----------- - Get the details of an active z/OSMF workflow + Get the details of an active z/OSMF workflow. USAGE ----- @@ -153,8 +153,8 @@ exports[`List Active Workflow Details should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: active-workflow-details.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n active-workflow-details | awd\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Get the details of an active z/OSMF workflow\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows list active-workflow-details [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --workflow-name | --wn (string)\\\\n\\\\n List active workflow details by specified workflow name.\\\\n\\\\n --workflow-key | --wk (string)\\\\n\\\\n List active workflow details by specified workflow key.\\\\n\\\\n --list-steps | --ls (boolean)\\\\n\\\\n Optional parameter for listing steps and their properties.\\\\n\\\\n --steps-summary-only | --sso (boolean)\\\\n\\\\n Optional parameter that lists steps summary only.\\\\n\\\\n --list-variables | --lv (boolean)\\\\n\\\\n Optional parameter for listing variables and their properties.\\\\n\\\\n --skip-workflow-summary | --sws (boolean)\\\\n\\\\n Optional parameter that skips the default workflow summary.\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - To list the details of an active workflow with key\\\\n \\\\\\"7c62c790-0340-86b2-61ce618d8f8c\\\\\\" including its steps and variables:\\\\n\\\\n $ zowe zos-workflows list active-workflow-details --workflow-key \\\\\\"7c62c790-0340-86b2-61ce618d8f8c\\\\\\" --list-steps --list-variables\\\\n\\\\n - To list the details of an active workflow with name\\\\n \\\\\\"testWorkflow\\\\\\" including its steps and variables:\\\\n\\\\n $ zowe zos-workflows list active-workflow-details --workflow-name \\\\\\"testWorkflow\\\\\\" --list-steps --list-variables\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n active-workflow-details | awd\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Get the details of an active z/OSMF workflow.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows list active-workflow-details [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --workflow-name | --wn (string)\\\\n\\\\n List active workflow details by specified workflow name.\\\\n\\\\n --workflow-key | --wk (string)\\\\n\\\\n List active workflow details by specified workflow key.\\\\n\\\\n --list-steps | --ls (boolean)\\\\n\\\\n Optional parameter for listing steps and their properties.\\\\n\\\\n --steps-summary-only | --sso (boolean)\\\\n\\\\n Optional parameter that lists steps summary only.\\\\n\\\\n --list-variables | --lv (boolean)\\\\n\\\\n Optional parameter for listing variables and their properties.\\\\n\\\\n --skip-workflow-summary | --sws (boolean)\\\\n\\\\n Optional parameter that skips the default workflow summary.\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - To list the details of an active workflow with key\\\\n \\\\\\"7c62c790-0340-86b2-61ce618d8f8c\\\\\\" including its steps and variables:\\\\n\\\\n $ zowe zos-workflows list active-workflow-details --workflow-key \\\\\\"7c62c790-0340-86b2-61ce618d8f8c\\\\\\" --list-steps --list-variables\\\\n\\\\n - To list the details of an active workflow with name\\\\n \\\\\\"testWorkflow\\\\\\" including its steps and variables:\\\\n\\\\n $ zowe zos-workflows list active-workflow-details --workflow-name \\\\\\"testWorkflow\\\\\\" --list-steps --list-variables\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n active-workflow-details | awd\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Get the details of an active z/OSMF workflow\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows list active-workflow-details [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --workflow-name | --wn (string)\\\\n\\\\n List active workflow details by specified workflow name.\\\\n\\\\n --workflow-key | --wk (string)\\\\n\\\\n List active workflow details by specified workflow key.\\\\n\\\\n --list-steps | --ls (boolean)\\\\n\\\\n Optional parameter for listing steps and their properties.\\\\n\\\\n --steps-summary-only | --sso (boolean)\\\\n\\\\n Optional parameter that lists steps summary only.\\\\n\\\\n --list-variables | --lv (boolean)\\\\n\\\\n Optional parameter for listing variables and their properties.\\\\n\\\\n --skip-workflow-summary | --sws (boolean)\\\\n\\\\n Optional parameter that skips the default workflow summary.\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - To list the details of an active workflow with key\\\\n \\\\\\"7c62c790-0340-86b2-61ce618d8f8c\\\\\\" including its steps and variables:\\\\n\\\\n $ zowe zos-workflows list active-workflow-details --workflow-key \\\\\\"7c62c790-0340-86b2-61ce618d8f8c\\\\\\" --list-steps --list-variables\\\\n\\\\n - To list the details of an active workflow with name\\\\n \\\\\\"testWorkflow\\\\\\" including its steps and variables:\\\\n\\\\n $ zowe zos-workflows list active-workflow-details --workflow-name \\\\\\"testWorkflow\\\\\\" --list-steps --list-variables\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n active-workflow-details | awd\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Get the details of an active z/OSMF workflow.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows list active-workflow-details [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --workflow-name | --wn (string)\\\\n\\\\n List active workflow details by specified workflow name.\\\\n\\\\n --workflow-key | --wk (string)\\\\n\\\\n List active workflow details by specified workflow key.\\\\n\\\\n --list-steps | --ls (boolean)\\\\n\\\\n Optional parameter for listing steps and their properties.\\\\n\\\\n --steps-summary-only | --sso (boolean)\\\\n\\\\n Optional parameter that lists steps summary only.\\\\n\\\\n --list-variables | --lv (boolean)\\\\n\\\\n Optional parameter for listing variables and their properties.\\\\n\\\\n --skip-workflow-summary | --sws (boolean)\\\\n\\\\n Optional parameter that skips the default workflow summary.\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - To list the details of an active workflow with key\\\\n \\\\\\"7c62c790-0340-86b2-61ce618d8f8c\\\\\\" including its steps and variables:\\\\n\\\\n $ zowe zos-workflows list active-workflow-details --workflow-key \\\\\\"7c62c790-0340-86b2-61ce618d8f8c\\\\\\" --list-steps --list-variables\\\\n\\\\n - To list the details of an active workflow with name\\\\n \\\\\\"testWorkflow\\\\\\" including its steps and variables:\\\\n\\\\n $ zowe zos-workflows list active-workflow-details --workflow-name \\\\\\"testWorkflow\\\\\\" --list-steps --list-variables\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/workflows/__integration__/list/activeWorkflows/__snapshots__/cli.workflows.list.activeWorkflows.integration.test.ts.snap b/packages/cli/__tests__/workflows/__integration__/list/activeWorkflows/__snapshots__/cli.workflows.list.activeWorkflows.integration.test.ts.snap index 91644fdd6d..7b18277e80 100644 --- a/packages/cli/__tests__/workflows/__integration__/list/activeWorkflows/__snapshots__/cli.workflows.list.activeWorkflows.integration.test.ts.snap +++ b/packages/cli/__tests__/workflows/__integration__/list/activeWorkflows/__snapshots__/cli.workflows.list.activeWorkflows.integration.test.ts.snap @@ -13,7 +13,7 @@ exports[`List Active Workflows should display the help 1`] = ` List active workflow instance(s) in z/OSMF. Multiple filters can be used together. - Omitting all options will list all workflows on the sysplex + Omitting all options will list all workflows on the sysplex. USAGE ----- @@ -198,8 +198,8 @@ exports[`List Active Workflows should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: active-workflows.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n active-workflows | aw\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n List active workflow instance(s) in z/OSMF.\\\\n Multiple filters can be used together.\\\\n Omitting all options will list all workflows on the sysplex\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows list active-workflows [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --workflow-name | --wn (string)\\\\n\\\\n Filter by workflow name. For wildcard use .*\\\\n\\\\n --category | --cat (string)\\\\n\\\\n Filter by the category of the workflows, which is either general or\\\\n configuration.\\\\n\\\\n --system | --sys (string)\\\\n\\\\n Filter by the nickname of the system on which the workflows is/are active.\\\\n\\\\n --owner | --ow (string)\\\\n\\\\n Filter by owner of the workflow(s) (a valid z/OS user ID).\\\\n\\\\n --vendor | --vd (string)\\\\n\\\\n Filter by the name of the vendor that provided the workflow(s) definition file.\\\\n\\\\n --status-name | --sn (string)\\\\n\\\\n Filter by the status of the workflow(s).\\\\n\\\\n Allowed values: in-progress, complete, automation-in-progress, canceled\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - List the workflow with name \\\\\\"testworkflow\\\\\\":\\\\n\\\\n $ zowe zos-workflows list active-workflows --wn \\\\\\"testworkflow\\\\\\"\\\\n\\\\n - List multiple active workflows on the entire syspex with\\\\n names containing\\\\\\"workflow\\\\\\":\\\\n\\\\n $ zowe zos-workflows list active-workflows --wn \\\\\\".*workflow.*\\\\\\"\\\\n\\\\n - List multiple active workflows on system \\\\\\"IBMSYS\\\\\\" with\\\\n names beginnig with \\\\\\"testW\\\\\\" that are in status \\\\\\"complete\\\\\\":\\\\n\\\\n $ zowe zos-workflows list active-workflows --wn \\\\\\"test.*\\\\\\" --sys \\\\\\"IBMSYS\\\\\\" --sn \\\\\\"complete\\\\\\"\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n active-workflows | aw\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n List active workflow instance(s) in z/OSMF.\\\\n Multiple filters can be used together.\\\\n Omitting all options will list all workflows on the sysplex.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows list active-workflows [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --workflow-name | --wn (string)\\\\n\\\\n Filter by workflow name. For wildcard use .*\\\\n\\\\n --category | --cat (string)\\\\n\\\\n Filter by the category of the workflows, which is either general or\\\\n configuration.\\\\n\\\\n --system | --sys (string)\\\\n\\\\n Filter by the nickname of the system on which the workflows is/are active.\\\\n\\\\n --owner | --ow (string)\\\\n\\\\n Filter by owner of the workflow(s) (a valid z/OS user ID).\\\\n\\\\n --vendor | --vd (string)\\\\n\\\\n Filter by the name of the vendor that provided the workflow(s) definition file.\\\\n\\\\n --status-name | --sn (string)\\\\n\\\\n Filter by the status of the workflow(s).\\\\n\\\\n Allowed values: in-progress, complete, automation-in-progress, canceled\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - List the workflow with name \\\\\\"testworkflow\\\\\\":\\\\n\\\\n $ zowe zos-workflows list active-workflows --wn \\\\\\"testworkflow\\\\\\"\\\\n\\\\n - List multiple active workflows on the entire syspex with\\\\n names containing\\\\\\"workflow\\\\\\":\\\\n\\\\n $ zowe zos-workflows list active-workflows --wn \\\\\\".*workflow.*\\\\\\"\\\\n\\\\n - List multiple active workflows on system \\\\\\"IBMSYS\\\\\\" with\\\\n names beginnig with \\\\\\"testW\\\\\\" that are in status \\\\\\"complete\\\\\\":\\\\n\\\\n $ zowe zos-workflows list active-workflows --wn \\\\\\"test.*\\\\\\" --sys \\\\\\"IBMSYS\\\\\\" --sn \\\\\\"complete\\\\\\"\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n active-workflows | aw\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n List active workflow instance(s) in z/OSMF.\\\\n Multiple filters can be used together.\\\\n Omitting all options will list all workflows on the sysplex\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows list active-workflows [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --workflow-name | --wn (string)\\\\n\\\\n Filter by workflow name. For wildcard use .*\\\\n\\\\n --category | --cat (string)\\\\n\\\\n Filter by the category of the workflows, which is either general or\\\\n configuration.\\\\n\\\\n --system | --sys (string)\\\\n\\\\n Filter by the nickname of the system on which the workflows is/are active.\\\\n\\\\n --owner | --ow (string)\\\\n\\\\n Filter by owner of the workflow(s) (a valid z/OS user ID).\\\\n\\\\n --vendor | --vd (string)\\\\n\\\\n Filter by the name of the vendor that provided the workflow(s) definition file.\\\\n\\\\n --status-name | --sn (string)\\\\n\\\\n Filter by the status of the workflow(s).\\\\n\\\\n Allowed values: in-progress, complete, automation-in-progress, canceled\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - List the workflow with name \\\\\\"testworkflow\\\\\\":\\\\n\\\\n $ zowe zos-workflows list active-workflows --wn \\\\\\"testworkflow\\\\\\"\\\\n\\\\n - List multiple active workflows on the entire syspex with\\\\n names containing\\\\\\"workflow\\\\\\":\\\\n\\\\n $ zowe zos-workflows list active-workflows --wn \\\\\\".*workflow.*\\\\\\"\\\\n\\\\n - List multiple active workflows on system \\\\\\"IBMSYS\\\\\\" with\\\\n names beginnig with \\\\\\"testW\\\\\\" that are in status \\\\\\"complete\\\\\\":\\\\n\\\\n $ zowe zos-workflows list active-workflows --wn \\\\\\"test.*\\\\\\" --sys \\\\\\"IBMSYS\\\\\\" --sn \\\\\\"complete\\\\\\"\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n active-workflows | aw\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n List active workflow instance(s) in z/OSMF.\\\\n Multiple filters can be used together.\\\\n Omitting all options will list all workflows on the sysplex.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-workflows list active-workflows [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --workflow-name | --wn (string)\\\\n\\\\n Filter by workflow name. For wildcard use .*\\\\n\\\\n --category | --cat (string)\\\\n\\\\n Filter by the category of the workflows, which is either general or\\\\n configuration.\\\\n\\\\n --system | --sys (string)\\\\n\\\\n Filter by the nickname of the system on which the workflows is/are active.\\\\n\\\\n --owner | --ow (string)\\\\n\\\\n Filter by owner of the workflow(s) (a valid z/OS user ID).\\\\n\\\\n --vendor | --vd (string)\\\\n\\\\n Filter by the name of the vendor that provided the workflow(s) definition file.\\\\n\\\\n --status-name | --sn (string)\\\\n\\\\n Filter by the status of the workflow(s).\\\\n\\\\n Allowed values: in-progress, complete, automation-in-progress, canceled\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - List the workflow with name \\\\\\"testworkflow\\\\\\":\\\\n\\\\n $ zowe zos-workflows list active-workflows --wn \\\\\\"testworkflow\\\\\\"\\\\n\\\\n - List multiple active workflows on the entire syspex with\\\\n names containing\\\\\\"workflow\\\\\\":\\\\n\\\\n $ zowe zos-workflows list active-workflows --wn \\\\\\".*workflow.*\\\\\\"\\\\n\\\\n - List multiple active workflows on system \\\\\\"IBMSYS\\\\\\" with\\\\n names beginnig with \\\\\\"testW\\\\\\" that are in status \\\\\\"complete\\\\\\":\\\\n\\\\n $ zowe zos-workflows list active-workflows --wn \\\\\\"test.*\\\\\\" --sys \\\\\\"IBMSYS\\\\\\" --sn \\\\\\"complete\\\\\\"\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/workflows/__unit__/archive/__snapshots__/Archive.definition.unit.test.ts.snap b/packages/cli/__tests__/workflows/__unit__/archive/__snapshots__/Archive.definition.unit.test.ts.snap index 1f90e15b2a..09ddae7b3c 100644 --- a/packages/cli/__tests__/workflows/__unit__/archive/__snapshots__/Archive.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/workflows/__unit__/archive/__snapshots__/Archive.definition.unit.test.ts.snap @@ -4,6 +4,7 @@ exports[`zos-workflows list definition should not have changed 1`] = ` Object { "description": "Archive workflow instance in z/OSMF.", "name": "archive", + "summary": "Archive workflow instance in z/OSMF", "type": "group", } `; diff --git a/packages/cli/__tests__/workflows/__unit__/create/__snapshots__/Create.definition.unit.test.ts.snap b/packages/cli/__tests__/workflows/__unit__/create/__snapshots__/Create.definition.unit.test.ts.snap index 1412039601..ed7d5db11c 100644 --- a/packages/cli/__tests__/workflows/__unit__/create/__snapshots__/Create.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/workflows/__unit__/create/__snapshots__/Create.definition.unit.test.ts.snap @@ -7,6 +7,7 @@ Object { ], "description": "Create a z/OSMF workflow on a z/OS system.", "name": "create", + "summary": "Create a z/OSMF workflow on a z/OS system", "type": "group", } `; diff --git a/packages/cli/__tests__/workflows/__unit__/create/dataset/__snapshots__/Dataset.definition.unit.test.ts.snap b/packages/cli/__tests__/workflows/__unit__/create/dataset/__snapshots__/Dataset.definition.unit.test.ts.snap index 193d760b9b..1b549f9b21 100644 --- a/packages/cli/__tests__/workflows/__unit__/create/dataset/__snapshots__/Dataset.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/workflows/__unit__/create/dataset/__snapshots__/Dataset.definition.unit.test.ts.snap @@ -5,7 +5,7 @@ Object { "aliases": Array [ "wfds", ], - "description": "Create a z/OSMF workflow on a z/OS system using a Data set", + "description": "Create a z/OSMF workflow on a z/OS system using a data set.", "examples": Array [ Object { "description": "Create a workflow with name \\"testworkflow\\" using the data set \\"TESTID.WKFLOW\\" that contains the workflow definition xml on the system \\"TESTM1\\" with owner \\"OTHERID\\" and delete workflow with the same name if it already exists in z/OSMF", @@ -130,6 +130,7 @@ Object { "zosmf", ], }, + "summary": "Create a z/OSMF workflow on a z/OS system using a data set", "type": "command", } `; diff --git a/packages/cli/__tests__/workflows/__unit__/create/localfile/__snapshots__/LocalFile.definition.unit.test.ts.snap b/packages/cli/__tests__/workflows/__unit__/create/localfile/__snapshots__/LocalFile.definition.unit.test.ts.snap index 2b4fe16344..11a8134926 100644 --- a/packages/cli/__tests__/workflows/__unit__/create/localfile/__snapshots__/LocalFile.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/workflows/__unit__/create/localfile/__snapshots__/LocalFile.definition.unit.test.ts.snap @@ -5,7 +5,7 @@ Object { "aliases": Array [ "wflf", ], - "description": "Create a z/OSMF workflow on a z/OS system using a Local file", + "description": "Create a z/OSMF workflow on a z/OS system using a local file.", "examples": Array [ Object { "description": "Create a workflow with name \\"testworkflow\\" using the local file \\"TESTID_WKFLOW.xml\\" that contains the workflow definition xml on the system \\"TESTM1\\" with owner \\"OTHERID\\" and delete workflow with the same name if it already exists in z/OSMF", @@ -107,7 +107,7 @@ Object { "aliases": Array [ "rd", ], - "description": "The remote uss directory where the files are to be uploaded. The directory has to exist", + "description": "The remote USS directory where the files are to be uploaded. The directory has to exist.", "name": "remote-directory", "required": false, "type": "string", @@ -137,6 +137,7 @@ Object { "zosmf", ], }, + "summary": "Create a z/OSMF workflow on a z/OS system using a local file", "type": "command", } `; diff --git a/packages/cli/__tests__/workflows/__unit__/create/ussfile/__snapshots__/UssFile.definition.unit.test.ts.snap b/packages/cli/__tests__/workflows/__unit__/create/ussfile/__snapshots__/UssFile.definition.unit.test.ts.snap index 0778ee62ce..96865351f2 100644 --- a/packages/cli/__tests__/workflows/__unit__/create/ussfile/__snapshots__/UssFile.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/workflows/__unit__/create/ussfile/__snapshots__/UssFile.definition.unit.test.ts.snap @@ -5,7 +5,7 @@ Object { "aliases": Array [ "wfuf", ], - "description": "Create a workflow instance in z/OSMF using a USS file", + "description": "Create a workflow instance in z/OSMF using a USS file.", "examples": Array [ Object { "description": "Create a workflow with name \\"testworkflow\\" using uss file \\"/path/workflow.xml\\" containing workflow definition, on system \\"TESTM1\\" with owner \\"OTHERID\\" and delete workflow with the same name if it already exists in z/OSMF", @@ -30,7 +30,7 @@ Object { "aliases": Array [ "uf", ], - "description": "Uss file that contains workflow definition.", + "description": "USS file that contains workflow definition.", "name": "uss-file", "required": true, "type": "string", @@ -130,6 +130,7 @@ Object { "zosmf", ], }, + "summary": "Create a workflow instance in z/OSMF using a USS file", "type": "command", } `; diff --git a/packages/cli/__tests__/workflows/__unit__/delete/__snapshots__/Delete.definition.unit.test.ts.snap b/packages/cli/__tests__/workflows/__unit__/delete/__snapshots__/Delete.definition.unit.test.ts.snap index 08eddc40cf..9776a46436 100644 --- a/packages/cli/__tests__/workflows/__unit__/delete/__snapshots__/Delete.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/workflows/__unit__/delete/__snapshots__/Delete.definition.unit.test.ts.snap @@ -7,6 +7,7 @@ Object { ], "description": "Delete an active workflow or an archived workflow from z/OSMF.", "name": "delete", + "summary": "Delete an active workflow or an archived workflow from z/OSMF", "type": "group", } `; diff --git a/packages/cli/__tests__/workflows/__unit__/delete/deleteActiveWorkflow/__snapshots__/deleteActiveWorkflow.definition.unit.test.ts.snap b/packages/cli/__tests__/workflows/__unit__/delete/deleteActiveWorkflow/__snapshots__/deleteActiveWorkflow.definition.unit.test.ts.snap index 3580b72123..aa837d38b3 100644 --- a/packages/cli/__tests__/workflows/__unit__/delete/deleteActiveWorkflow/__snapshots__/deleteActiveWorkflow.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/workflows/__unit__/delete/deleteActiveWorkflow/__snapshots__/deleteActiveWorkflow.definition.unit.test.ts.snap @@ -5,7 +5,7 @@ Object { "aliases": Array [ "aw", ], - "description": "Delete an active workflow instance in z/OSMF", + "description": "Delete an active workflow instance in z/OSMF.", "examples": Array [ Object { "description": "To delete a workflow instance in z/OSMF with workflow key \\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\"", @@ -52,6 +52,7 @@ Object { "zosmf", ], }, + "summary": "Delete an active workflow instance in z/OSMF", "type": "command", } `; diff --git a/packages/cli/__tests__/workflows/__unit__/delete/deleteArchivedWorkflow/__snapshots__/deleteArchivedWorkflow.definition.unit.test.ts.snap b/packages/cli/__tests__/workflows/__unit__/delete/deleteArchivedWorkflow/__snapshots__/deleteArchivedWorkflow.definition.unit.test.ts.snap index 154745e69f..c1c443c036 100644 --- a/packages/cli/__tests__/workflows/__unit__/delete/deleteArchivedWorkflow/__snapshots__/deleteArchivedWorkflow.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/workflows/__unit__/delete/deleteArchivedWorkflow/__snapshots__/deleteArchivedWorkflow.definition.unit.test.ts.snap @@ -5,7 +5,7 @@ Object { "aliases": Array [ "arw", ], - "description": "Delete an archived workflow from z/OSMF", + "description": "Delete an archived workflow from z/OSMF.", "examples": Array [ Object { "description": "To delete an archived workflow from z/OSMF with workflow key \\"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\\"", @@ -52,6 +52,7 @@ Object { "zosmf", ], }, + "summary": "Delete an archived workflow from z/OSMF", "type": "command", } `; diff --git a/packages/cli/__tests__/workflows/__unit__/list/__snapshots__/List.definition.unit.test.ts.snap b/packages/cli/__tests__/workflows/__unit__/list/__snapshots__/List.definition.unit.test.ts.snap index c685737f27..6a960c9145 100644 --- a/packages/cli/__tests__/workflows/__unit__/list/__snapshots__/List.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/workflows/__unit__/list/__snapshots__/List.definition.unit.test.ts.snap @@ -7,6 +7,7 @@ Object { ], "description": "List the z/OSMF workflows for a system or a sysplex with filter options.", "name": "list", + "summary": "List the z/OSMF workflows for a system or a sysplex with filter options", "type": "group", } `; diff --git a/packages/cli/__tests__/workflows/__unit__/list/activeWorkflow/__snapshots__/ActiveWorkflows.definition.unit.test.ts.snap b/packages/cli/__tests__/workflows/__unit__/list/activeWorkflow/__snapshots__/ActiveWorkflows.definition.unit.test.ts.snap index 01dca082c1..c0ab25c13d 100644 --- a/packages/cli/__tests__/workflows/__unit__/list/activeWorkflow/__snapshots__/ActiveWorkflows.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/workflows/__unit__/list/activeWorkflow/__snapshots__/ActiveWorkflows.definition.unit.test.ts.snap @@ -7,7 +7,7 @@ Object { ], "description": "List active workflow instance(s) in z/OSMF. Multiple filters can be used together. -Omitting all options will list all workflows on the sysplex", +Omitting all options will list all workflows on the sysplex.", "examples": Array [ Object { "description": "List the workflow with name \\"testworkflow\\"", @@ -94,7 +94,7 @@ Omitting all options will list all workflows on the sysplex", "zosmf", ], }, - "summary": "List active workflow instance(s) in z/OSMF.", + "summary": "List active workflow instance(s) in z/OSMF", "type": "command", } `; diff --git a/packages/cli/__tests__/workflows/__unit__/list/activeWorkflowDetails/__snapshots__/ActiveWorkflowDetails.definition.unit.test.ts.snap b/packages/cli/__tests__/workflows/__unit__/list/activeWorkflowDetails/__snapshots__/ActiveWorkflowDetails.definition.unit.test.ts.snap index 02c816fb24..0f5af187c4 100644 --- a/packages/cli/__tests__/workflows/__unit__/list/activeWorkflowDetails/__snapshots__/ActiveWorkflowDetails.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/workflows/__unit__/list/activeWorkflowDetails/__snapshots__/ActiveWorkflowDetails.definition.unit.test.ts.snap @@ -5,7 +5,7 @@ Object { "aliases": Array [ "awd", ], - "description": "Get the details of an active z/OSMF workflow", + "description": "Get the details of an active z/OSMF workflow.", "examples": Array [ Object { "description": "To list the details of an active workflow with key \\"7c62c790-0340-86b2-61ce618d8f8c\\" including its steps and variables", @@ -92,6 +92,7 @@ Object { "zosmf", ], }, + "summary": "Get the details of an active z/OSMF workflow", "type": "command", } `; diff --git a/packages/cli/__tests__/workflows/__unit__/list/archivedWorkflows/__snapshots__/ArchivedWorkflows.definition.unit.test.ts.snap b/packages/cli/__tests__/workflows/__unit__/list/archivedWorkflows/__snapshots__/ArchivedWorkflows.definition.unit.test.ts.snap index bc8edb4cc5..c90c54ce71 100644 --- a/packages/cli/__tests__/workflows/__unit__/list/archivedWorkflows/__snapshots__/ArchivedWorkflows.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/workflows/__unit__/list/archivedWorkflows/__snapshots__/ArchivedWorkflows.definition.unit.test.ts.snap @@ -13,7 +13,7 @@ Object { "zosmf", ], }, - "summary": "List all archived workflows for a system.", + "summary": "List all archived workflows for a system", "type": "command", } `; diff --git a/packages/cli/__tests__/workflows/__unit__/list/retrieveWorkflowDefinition/__snapshots__/RetrieveWorkflowDefinition.definition.unit.test.ts.snap b/packages/cli/__tests__/workflows/__unit__/list/retrieveWorkflowDefinition/__snapshots__/RetrieveWorkflowDefinition.definition.unit.test.ts.snap index d10cd1f402..6e1a5ff287 100644 --- a/packages/cli/__tests__/workflows/__unit__/list/retrieveWorkflowDefinition/__snapshots__/RetrieveWorkflowDefinition.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/workflows/__unit__/list/retrieveWorkflowDefinition/__snapshots__/RetrieveWorkflowDefinition.definition.unit.test.ts.snap @@ -50,6 +50,7 @@ Object { "zosmf", ], }, + "summary": "Retrieve the contents of a z/OSMF workflow definition from a z/OS system", "type": "command", } `; diff --git a/packages/cli/__tests__/workflows/__unit__/start/__snapshots__/Start.definition.unit.test.ts.snap b/packages/cli/__tests__/workflows/__unit__/start/__snapshots__/Start.definition.unit.test.ts.snap index dfe9bbd6af..b389b1f2ab 100644 --- a/packages/cli/__tests__/workflows/__unit__/start/__snapshots__/Start.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/workflows/__unit__/start/__snapshots__/Start.definition.unit.test.ts.snap @@ -7,6 +7,7 @@ Object { ], "description": "Start a z/OSMF workflow on a z/OS system.", "name": "start", + "summary": "Start a z/OSMF workflow on a z/OS system", "type": "group", } `; diff --git a/packages/cli/__tests__/workflows/__unit__/start/workflowFull/__snapshots__/WorkflowFull.definition.unit.test.ts.snap b/packages/cli/__tests__/workflows/__unit__/start/workflowFull/__snapshots__/WorkflowFull.definition.unit.test.ts.snap index f59af1dd8f..d9da9d9c6e 100644 --- a/packages/cli/__tests__/workflows/__unit__/start/workflowFull/__snapshots__/WorkflowFull.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/workflows/__unit__/start/workflowFull/__snapshots__/WorkflowFull.definition.unit.test.ts.snap @@ -86,6 +86,7 @@ leaveConflict: Automation is stopped. The user must resolve the conflict manuall "zosmf", ], }, + "summary": "Will run workflow from the beginning to the end or to the first manual step", "type": "command", } `; diff --git a/packages/cli/__tests__/workflows/__unit__/start/workflowStep/__snapshots__/WorkflowStep.definition.unit.test.ts.snap b/packages/cli/__tests__/workflows/__unit__/start/workflowStep/__snapshots__/WorkflowStep.definition.unit.test.ts.snap index 26ca830087..280ce00655 100644 --- a/packages/cli/__tests__/workflows/__unit__/start/workflowStep/__snapshots__/WorkflowStep.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/workflows/__unit__/start/workflowStep/__snapshots__/WorkflowStep.definition.unit.test.ts.snap @@ -95,6 +95,7 @@ leaveConflict: Automation is stopped. The user must resolve the conflict manuall "zosmf", ], }, + "summary": "Will run given step of workflow instance plus following steps if specified by --perform-following-steps option", "type": "command", } `; diff --git a/packages/cli/__tests__/zosconsole/__integration__/root/__scripts__/invalid_option.sh b/packages/cli/__tests__/zosconsole/__integration__/root/__scripts__/invalid_option.sh index b69025527f..2c75b32366 100755 --- a/packages/cli/__tests__/zosconsole/__integration__/root/__scripts__/invalid_option.sh +++ b/packages/cli/__tests__/zosconsole/__integration__/root/__scripts__/invalid_option.sh @@ -1,6 +1,6 @@ #!/bin/bash set -e -echo "================Z/OS CONSOLE INVALID PARAMETERS===============" +echo "================Z/OS CONSOLE INVALID OPTION===============" zowe zos-console --foo-bar exit $? diff --git a/packages/cli/__tests__/zosconsole/__integration__/root/__snapshots__/cli.zos-console.integration.test.ts.snap b/packages/cli/__tests__/zosconsole/__integration__/root/__snapshots__/cli.zos-console.integration.test.ts.snap index 2c863c668c..c8dd0ebac4 100644 --- a/packages/cli/__tests__/zosconsole/__integration__/root/__snapshots__/cli.zos-console.integration.test.ts.snap +++ b/packages/cli/__tests__/zosconsole/__integration__/root/__snapshots__/cli.zos-console.integration.test.ts.snap @@ -56,39 +56,3 @@ exports[`zos-console should display the help 1`] = ` \\"data\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Interact with z/OSMF console services. Issue z/OS console commands and collect\\\\n responses. z/OS console services establishes extended MCS (EMCS) consoles on\\\\n behalf of the user, which are used to issue the commands and collect responses.\\\\n\\\\n Important! Before you use commands in the zos-console command group, ensure that\\\\n you understand the implications of issuing z/OS console commands in your\\\\n environment.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-console \\\\n\\\\n Where is one of the following:\\\\n\\\\n GROUPS\\\\n ------\\\\n\\\\n collect Collect z/OS console command responses\\\\n issue Issue z/OS console commands \\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" }" `; - -exports[`zos-console should fail with invalid option 1`] = ` -"Command Error: -Unknown arguments: foo-bar, fooBar -Command failed due to improper syntax -Did you mean: zos-console collect? - -Command entered: \\"zos-console --foo-bar\\" -Use \\"zowe zos-console --help\\" to view groups, commands, and options. -Error Details: -Unknown arguments: foo-bar, fooBar -" -`; - -exports[`zos-console should fail with invalid option 2`] = ` -"================Z/OS CONSOLE INVALID PARAMETERS=============== -" -`; - -exports[`zos-console should fail with invalid parameter 1`] = ` -"Command Error: -Unknown argument: foobar -Command failed due to improper syntax -Did you mean: zos-console collect? - -Command entered: \\"zos-console foobar\\" -Use \\"zowe zos-console --help\\" to view groups, commands, and options. -Error Details: -Unknown argument: foobar -" -`; - -exports[`zos-console should fail with invalid parameter 2`] = ` -"================Z/OS CONSOLE INVALID PARAMETERS=============== -" -`; diff --git a/packages/cli/__tests__/zosconsole/__integration__/root/cli.zos-console.integration.test.ts b/packages/cli/__tests__/zosconsole/__integration__/root/cli.zos-console.integration.test.ts index ca03128837..a9423c17ef 100644 --- a/packages/cli/__tests__/zosconsole/__integration__/root/cli.zos-console.integration.test.ts +++ b/packages/cli/__tests__/zosconsole/__integration__/root/cli.zos-console.integration.test.ts @@ -36,14 +36,24 @@ describe("zos-console", () => { it("should fail with invalid parameter", async () => { const response = runCliScript(__dirname + "/__scripts__/invalid_parameter.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); - expect(response.stderr.toString()).toMatchSnapshot(); - expect(response.stdout.toString()).toMatchSnapshot(); + expect(response.stdout.toString()).toContain('================Z/OS CONSOLE INVALID PARAMETERS==============='); + expect(response.stderr.toString()).toContain('Unknown argument: foobar'); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Did you mean: zos-console collect'); + expect(response.stderr.toString()).toContain('Command entered: "zos-console foobar"'); + expect(response.stderr.toString()).toContain('Use "zowe zos-console --help" to view groups, commands, and options.'); + expect(response.stderr.toString()).toContain('Error: Unknown argument: foobar'); }); it("should fail with invalid option", async () => { const response = runCliScript(__dirname + "/__scripts__/invalid_option.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); - expect(response.stderr.toString()).toMatchSnapshot(); - expect(response.stdout.toString()).toMatchSnapshot(); + expect(response.stdout.toString()).toContain('================Z/OS CONSOLE INVALID OPTION==============='); + expect(response.stderr.toString()).toContain('Unknown arguments: foo-bar, fooBar'); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Did you mean: zos-console collect'); + expect(response.stderr.toString()).toContain('Command entered: "zos-console --foo-bar"'); + expect(response.stderr.toString()).toContain('Use "zowe zos-console --help" to view groups, commands, and options.'); + expect(response.stderr.toString()).toContain('Error: Unknown arguments: foo-bar, fooBar'); }); }); diff --git a/packages/cli/__tests__/zosfiles/__integration__/compare/ds/__snapshots__/cli.files.compare.ds.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/compare/ds/__snapshots__/cli.files.compare.ds.integration.test.ts.snap index 700ed4e2cd..544d610061 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/compare/ds/__snapshots__/cli.files.compare.ds.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/compare/ds/__snapshots__/cli.files.compare.ds.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Compare two data sets should display the help 1`] = ` DESCRIPTION ----------- - Compare content of two z/OS data sets on your terminal (stdout). + Compare the contents of two z/OS data sets in your terminal (stdout). USAGE ----- @@ -36,7 +36,7 @@ exports[`Compare two data sets should display the help 1`] = ` Transfer the content of the first data set in binary mode (no EBCDIC to ASCII conversion). If binary mode is set and the binary2 flag is not set then both - datasets are transferred in binary mode. + data sets are transferred in binary mode. --binary2 | --b2 (boolean) @@ -96,7 +96,7 @@ exports[`Compare two data sets should display the help 1`] = ` --browser-view | --bv (boolean) - Opens the diffs between two given files in browser + Opens the diffs between two given files in browser. --response-timeout | --rto (number) @@ -212,8 +212,8 @@ exports[`Compare two data sets should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: data-set.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Compare content of two z/OS data sets on your terminal (stdout).\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files compare data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName1\\\\t\\\\t (string)\\\\n\\\\n The name of the first data set you want to compare.\\\\n\\\\n dataSetName2\\\\t\\\\t (string)\\\\n\\\\n The name of the second data set you want to compare.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Transfer the content of the first data set in binary mode (no EBCDIC to ASCII\\\\n conversion). If binary mode is set and the binary2 flag is not set then both\\\\n datasets are transferred in binary mode.\\\\n\\\\n --binary2 | --b2 (boolean)\\\\n\\\\n Transfer the content of the second data set in binary mode.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Transfer the content of the first data set with encoding mode, which means that\\\\n data conversion is performed using the file encoding specified. If encoding mode\\\\n is set and the encoding2 flag is not set both data sets are transferred in\\\\n encoding mode.\\\\n\\\\n --encoding2 | --ec2 (string)\\\\n\\\\n Transfer the content of the second data set with encoding mode.\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Transfer the content for the first data set in record mode, which means that no\\\\n data conversion is performed and the record length is prepended to the data. The\\\\n data transfer process returns each line as-is, without translation. No\\\\n delimiters are added between records. If encoding mode is set and the encoding2\\\\n flag is not set both data sets are transferred in encoding mode. This option\\\\n conflicts with binary mode.\\\\n\\\\n --record2 | --r2 (boolean)\\\\n\\\\n Transfer the content for the second data set in record mode. Conflicts with\\\\n binary2.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the first data set resides. You can use this\\\\n option at any time. However, the VOLSER is required only when the data set is\\\\n not cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --volume-serial2 | --vs2 (string)\\\\n\\\\n The volume serial (VOLSER) where the second data set resides.\\\\n\\\\n --seqnum | --sn (boolean)\\\\n\\\\n If you are comparing two files that contain sequence numbers, this option\\\\n controls if the sequences numbers are removed from the end of each string. The\\\\n default is to keep the sequence numbers. Use the --no-seqnum option to not\\\\n include them.\\\\n\\\\n Default value: true\\\\n\\\\n --context-lines | --cl (number)\\\\n\\\\n The number of context lines that display before and after detected non-matching\\\\n lines. By default all matching lines display. If you want to limit the amount of\\\\n data returned to only lines with differences use the context lines option to\\\\n reduce the matching lines to only those before and after non-matching lines.\\\\n Using the value of 0 strips all matching lines.\\\\n\\\\n --browser-view | --bv (boolean)\\\\n\\\\n Opens the diffs between two given files in browser\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Compare the contents of the data set members\\\\n \\\\\\"sys1.samplib(antptso)\\\\\\" and \\\\\\"sys1.samplib(antxtso)\\\\\\":\\\\n\\\\n $ zowe zos-files compare data-set \\\\\\"sys1.samplib(antptso)\\\\\\" \\\\\\"sys1.samplib(antxtso)\\\\\\"\\\\n\\\\n - Compare the contents of the data set members\\\\n \\\\\\"sys1.samplib(antptso)\\\\\\" and \\\\\\"sys1.samplib(antxtso)\\\\\\" without sequence numbers:\\\\n\\\\n $ zowe zos-files compare data-set \\\\\\"sys1.samplib(antptso)\\\\\\" \\\\\\"sys1.samplib(antxtso)\\\\\\" --no-seqnum\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Compare the contents of two z/OS data sets in your terminal (stdout).\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files compare data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName1\\\\t\\\\t (string)\\\\n\\\\n The name of the first data set you want to compare.\\\\n\\\\n dataSetName2\\\\t\\\\t (string)\\\\n\\\\n The name of the second data set you want to compare.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Transfer the content of the first data set in binary mode (no EBCDIC to ASCII\\\\n conversion). If binary mode is set and the binary2 flag is not set then both\\\\n data sets are transferred in binary mode.\\\\n\\\\n --binary2 | --b2 (boolean)\\\\n\\\\n Transfer the content of the second data set in binary mode.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Transfer the content of the first data set with encoding mode, which means that\\\\n data conversion is performed using the file encoding specified. If encoding mode\\\\n is set and the encoding2 flag is not set both data sets are transferred in\\\\n encoding mode.\\\\n\\\\n --encoding2 | --ec2 (string)\\\\n\\\\n Transfer the content of the second data set with encoding mode.\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Transfer the content for the first data set in record mode, which means that no\\\\n data conversion is performed and the record length is prepended to the data. The\\\\n data transfer process returns each line as-is, without translation. No\\\\n delimiters are added between records. If encoding mode is set and the encoding2\\\\n flag is not set both data sets are transferred in encoding mode. This option\\\\n conflicts with binary mode.\\\\n\\\\n --record2 | --r2 (boolean)\\\\n\\\\n Transfer the content for the second data set in record mode. Conflicts with\\\\n binary2.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the first data set resides. You can use this\\\\n option at any time. However, the VOLSER is required only when the data set is\\\\n not cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --volume-serial2 | --vs2 (string)\\\\n\\\\n The volume serial (VOLSER) where the second data set resides.\\\\n\\\\n --seqnum | --sn (boolean)\\\\n\\\\n If you are comparing two files that contain sequence numbers, this option\\\\n controls if the sequences numbers are removed from the end of each string. The\\\\n default is to keep the sequence numbers. Use the --no-seqnum option to not\\\\n include them.\\\\n\\\\n Default value: true\\\\n\\\\n --context-lines | --cl (number)\\\\n\\\\n The number of context lines that display before and after detected non-matching\\\\n lines. By default all matching lines display. If you want to limit the amount of\\\\n data returned to only lines with differences use the context lines option to\\\\n reduce the matching lines to only those before and after non-matching lines.\\\\n Using the value of 0 strips all matching lines.\\\\n\\\\n --browser-view | --bv (boolean)\\\\n\\\\n Opens the diffs between two given files in browser.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Compare the contents of the data set members\\\\n \\\\\\"sys1.samplib(antptso)\\\\\\" and \\\\\\"sys1.samplib(antxtso)\\\\\\":\\\\n\\\\n $ zowe zos-files compare data-set \\\\\\"sys1.samplib(antptso)\\\\\\" \\\\\\"sys1.samplib(antxtso)\\\\\\"\\\\n\\\\n - Compare the contents of the data set members\\\\n \\\\\\"sys1.samplib(antptso)\\\\\\" and \\\\\\"sys1.samplib(antxtso)\\\\\\" without sequence numbers:\\\\n\\\\n $ zowe zos-files compare data-set \\\\\\"sys1.samplib(antptso)\\\\\\" \\\\\\"sys1.samplib(antxtso)\\\\\\" --no-seqnum\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Compare content of two z/OS data sets on your terminal (stdout).\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files compare data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName1\\\\t\\\\t (string)\\\\n\\\\n The name of the first data set you want to compare.\\\\n\\\\n dataSetName2\\\\t\\\\t (string)\\\\n\\\\n The name of the second data set you want to compare.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Transfer the content of the first data set in binary mode (no EBCDIC to ASCII\\\\n conversion). If binary mode is set and the binary2 flag is not set then both\\\\n datasets are transferred in binary mode.\\\\n\\\\n --binary2 | --b2 (boolean)\\\\n\\\\n Transfer the content of the second data set in binary mode.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Transfer the content of the first data set with encoding mode, which means that\\\\n data conversion is performed using the file encoding specified. If encoding mode\\\\n is set and the encoding2 flag is not set both data sets are transferred in\\\\n encoding mode.\\\\n\\\\n --encoding2 | --ec2 (string)\\\\n\\\\n Transfer the content of the second data set with encoding mode.\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Transfer the content for the first data set in record mode, which means that no\\\\n data conversion is performed and the record length is prepended to the data. The\\\\n data transfer process returns each line as-is, without translation. No\\\\n delimiters are added between records. If encoding mode is set and the encoding2\\\\n flag is not set both data sets are transferred in encoding mode. This option\\\\n conflicts with binary mode.\\\\n\\\\n --record2 | --r2 (boolean)\\\\n\\\\n Transfer the content for the second data set in record mode. Conflicts with\\\\n binary2.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the first data set resides. You can use this\\\\n option at any time. However, the VOLSER is required only when the data set is\\\\n not cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --volume-serial2 | --vs2 (string)\\\\n\\\\n The volume serial (VOLSER) where the second data set resides.\\\\n\\\\n --seqnum | --sn (boolean)\\\\n\\\\n If you are comparing two files that contain sequence numbers, this option\\\\n controls if the sequences numbers are removed from the end of each string. The\\\\n default is to keep the sequence numbers. Use the --no-seqnum option to not\\\\n include them.\\\\n\\\\n Default value: true\\\\n\\\\n --context-lines | --cl (number)\\\\n\\\\n The number of context lines that display before and after detected non-matching\\\\n lines. By default all matching lines display. If you want to limit the amount of\\\\n data returned to only lines with differences use the context lines option to\\\\n reduce the matching lines to only those before and after non-matching lines.\\\\n Using the value of 0 strips all matching lines.\\\\n\\\\n --browser-view | --bv (boolean)\\\\n\\\\n Opens the diffs between two given files in browser\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Compare the contents of the data set members\\\\n \\\\\\"sys1.samplib(antptso)\\\\\\" and \\\\\\"sys1.samplib(antxtso)\\\\\\":\\\\n\\\\n $ zowe zos-files compare data-set \\\\\\"sys1.samplib(antptso)\\\\\\" \\\\\\"sys1.samplib(antxtso)\\\\\\"\\\\n\\\\n - Compare the contents of the data set members\\\\n \\\\\\"sys1.samplib(antptso)\\\\\\" and \\\\\\"sys1.samplib(antxtso)\\\\\\" without sequence numbers:\\\\n\\\\n $ zowe zos-files compare data-set \\\\\\"sys1.samplib(antptso)\\\\\\" \\\\\\"sys1.samplib(antxtso)\\\\\\" --no-seqnum\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Compare the contents of two z/OS data sets in your terminal (stdout).\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files compare data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName1\\\\t\\\\t (string)\\\\n\\\\n The name of the first data set you want to compare.\\\\n\\\\n dataSetName2\\\\t\\\\t (string)\\\\n\\\\n The name of the second data set you want to compare.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Transfer the content of the first data set in binary mode (no EBCDIC to ASCII\\\\n conversion). If binary mode is set and the binary2 flag is not set then both\\\\n data sets are transferred in binary mode.\\\\n\\\\n --binary2 | --b2 (boolean)\\\\n\\\\n Transfer the content of the second data set in binary mode.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Transfer the content of the first data set with encoding mode, which means that\\\\n data conversion is performed using the file encoding specified. If encoding mode\\\\n is set and the encoding2 flag is not set both data sets are transferred in\\\\n encoding mode.\\\\n\\\\n --encoding2 | --ec2 (string)\\\\n\\\\n Transfer the content of the second data set with encoding mode.\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Transfer the content for the first data set in record mode, which means that no\\\\n data conversion is performed and the record length is prepended to the data. The\\\\n data transfer process returns each line as-is, without translation. No\\\\n delimiters are added between records. If encoding mode is set and the encoding2\\\\n flag is not set both data sets are transferred in encoding mode. This option\\\\n conflicts with binary mode.\\\\n\\\\n --record2 | --r2 (boolean)\\\\n\\\\n Transfer the content for the second data set in record mode. Conflicts with\\\\n binary2.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the first data set resides. You can use this\\\\n option at any time. However, the VOLSER is required only when the data set is\\\\n not cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --volume-serial2 | --vs2 (string)\\\\n\\\\n The volume serial (VOLSER) where the second data set resides.\\\\n\\\\n --seqnum | --sn (boolean)\\\\n\\\\n If you are comparing two files that contain sequence numbers, this option\\\\n controls if the sequences numbers are removed from the end of each string. The\\\\n default is to keep the sequence numbers. Use the --no-seqnum option to not\\\\n include them.\\\\n\\\\n Default value: true\\\\n\\\\n --context-lines | --cl (number)\\\\n\\\\n The number of context lines that display before and after detected non-matching\\\\n lines. By default all matching lines display. If you want to limit the amount of\\\\n data returned to only lines with differences use the context lines option to\\\\n reduce the matching lines to only those before and after non-matching lines.\\\\n Using the value of 0 strips all matching lines.\\\\n\\\\n --browser-view | --bv (boolean)\\\\n\\\\n Opens the diffs between two given files in browser.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Compare the contents of the data set members\\\\n \\\\\\"sys1.samplib(antptso)\\\\\\" and \\\\\\"sys1.samplib(antxtso)\\\\\\":\\\\n\\\\n $ zowe zos-files compare data-set \\\\\\"sys1.samplib(antptso)\\\\\\" \\\\\\"sys1.samplib(antxtso)\\\\\\"\\\\n\\\\n - Compare the contents of the data set members\\\\n \\\\\\"sys1.samplib(antptso)\\\\\\" and \\\\\\"sys1.samplib(antxtso)\\\\\\" without sequence numbers:\\\\n\\\\n $ zowe zos-files compare data-set \\\\\\"sys1.samplib(antptso)\\\\\\" \\\\\\"sys1.samplib(antxtso)\\\\\\" --no-seqnum\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/copy/ds/__snapshots__/cli.files.copy.ds.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/copy/ds/__snapshots__/cli.files.copy.ds.integration.test.ts.snap index ecc02b8fa9..abf6986543 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/copy/ds/__snapshots__/cli.files.copy.ds.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/copy/ds/__snapshots__/cli.files.copy.ds.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Copy Data Set should display the help 1`] = ` DESCRIPTION ----------- - Copy a data set to another data set + Copy a data set to another data set. USAGE ----- @@ -36,7 +36,7 @@ exports[`Copy Data Set should display the help 1`] = ` --replace | --rep (boolean) Specify this option as true if you wish to replace like-named members in the - target dataset + target data set --response-timeout | --rto (number) @@ -171,8 +171,8 @@ exports[`Copy Data Set should display the help in json format 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: data-set.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Copy a data set to another data set\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files copy data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n fromDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy from\\\\n\\\\n toDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy to (data set must be\\\\n preallocated)\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --replace | --rep (boolean)\\\\n\\\\n Specify this option as true if you wish to replace like-named members in the\\\\n target dataset\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\"\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\"\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\"\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set named 'USER.TO.SET':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET\\\\\\"\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET' and replace like-named members:\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\" --replace\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Copy a data set to another data set.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files copy data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n fromDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy from\\\\n\\\\n toDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy to (data set must be\\\\n preallocated)\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --replace | --rep (boolean)\\\\n\\\\n Specify this option as true if you wish to replace like-named members in the\\\\n target data set\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\"\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\"\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\"\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set named 'USER.TO.SET':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET\\\\\\"\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET' and replace like-named members:\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\" --replace\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Copy a data set to another data set\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files copy data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n fromDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy from\\\\n\\\\n toDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy to (data set must be\\\\n preallocated)\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --replace | --rep (boolean)\\\\n\\\\n Specify this option as true if you wish to replace like-named members in the\\\\n target dataset\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\"\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\"\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\"\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set named 'USER.TO.SET':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET\\\\\\"\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET' and replace like-named members:\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\" --replace\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Copy a data set to another data set.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files copy data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n fromDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy from\\\\n\\\\n toDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy to (data set must be\\\\n preallocated)\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --replace | --rep (boolean)\\\\n\\\\n Specify this option as true if you wish to replace like-named members in the\\\\n target data set\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\"\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\"\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\"\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set named 'USER.TO.SET':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET\\\\\\"\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET' and replace like-named members:\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\" --replace\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/copy/dsclp/__snapshots__/cli.files.copy.dsclp.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/copy/dsclp/__snapshots__/cli.files.copy.dsclp.integration.test.ts.snap index db5d8aa541..a4b531b886 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/copy/dsclp/__snapshots__/cli.files.copy.dsclp.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/copy/dsclp/__snapshots__/cli.files.copy.dsclp.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Copy Data Set Cross LPAR should display the help 1`] = ` DESCRIPTION ----------- - Copy a data set to another data set on a specified LPAR + Copy a data set to another data set on a specified LPAR. USAGE ----- @@ -27,16 +27,16 @@ exports[`Copy Data Set Cross LPAR should display the help 1`] = ` toDataSetName (string) - The name of the data set that you want to copy to. If the dataset does not exist - it will be allocated automatically + The name of the data set that you want to copy to. If the data set does not + exist it will be allocated automatically OPTIONS ------- --replace | --rep (boolean) - Specify this option as true if you wish to replace the target dataset if it - already exists + Specify this option as true if you wish to replace the target data set if it + already exists. --target-data-class | --tdc (string) @@ -212,8 +212,8 @@ exports[`Copy Data Set Cross LPAR should display the help in json format 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: data-set-cross-lpar.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-cross-lpar | dsclp\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Copy a data set to another data set on a specified LPAR\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files copy data-set-cross-lpar [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n fromDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy from\\\\n\\\\n toDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy to. If the dataset does not exist\\\\n it will be allocated automatically\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --replace | --rep (boolean)\\\\n\\\\n Specify this option as true if you wish to replace the target dataset if it\\\\n already exists\\\\n\\\\n --target-data-class | --tdc (string)\\\\n\\\\n The SMS data class to use for the allocation of the target data set.\\\\n\\\\n --target-host | --th (string)\\\\n\\\\n The target z/OSMF server host name.\\\\n\\\\n --target-management-class | --tmc (string)\\\\n\\\\n The SMS management class to use for the allocation of the target data set.\\\\n\\\\n --target-password | --tpw (string)\\\\n\\\\n The target z/OSMF password, which can be the same as your TSO password.\\\\n\\\\n --target-port | --tp (number)\\\\n\\\\n The target z/OSMF server port.\\\\n\\\\n --target-storage-class | --tsc (string)\\\\n\\\\n The SMS storage class to use for the allocation of the target data set.\\\\n\\\\n --target-token-type | --ttt (string)\\\\n\\\\n The value of the token to pass to the API for the target system.\\\\n\\\\n --target-token-value | --ttv (string)\\\\n\\\\n The type of token to get and use for the API for the target system.\\\\n\\\\n --target-user | --tu (string)\\\\n\\\\n The target z/OSMF user name, which can be the same as your TSO login.\\\\n\\\\n --target-volume-serial | --tvs | --target-volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the target data set to be placed.\\\\n\\\\n --target-zosmf-profile | --t-zosmf-p | --target-zosmf-p (string)\\\\n\\\\n The name of a z/OSMF profile to load for the target host.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET' using the --target-zosmf-p option to specify the target host\\\\n using a zosmf profile:\\\\n\\\\n $ zowe zos-files copy data-set-cross-lpar \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\" --target-zosmf-p SYS1\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set-cross-lpar \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\" --target-zosmf-p SYS1\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set-cross-lpar \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\" --target-zosmf-p SYS1\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set named 'USER.TO.SET' using the --target-host, --target-user, and\\\\n --target-password options:\\\\n\\\\n $ zowe zos-files copy data-set-cross-lpar \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET\\\\\\" --target-host sys1.com --target-user user1 --target-password pass1\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-cross-lpar | dsclp\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Copy a data set to another data set on a specified LPAR.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files copy data-set-cross-lpar [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n fromDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy from\\\\n\\\\n toDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy to. If the data set does not\\\\n exist it will be allocated automatically\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --replace | --rep (boolean)\\\\n\\\\n Specify this option as true if you wish to replace the target data set if it\\\\n already exists.\\\\n\\\\n --target-data-class | --tdc (string)\\\\n\\\\n The SMS data class to use for the allocation of the target data set.\\\\n\\\\n --target-host | --th (string)\\\\n\\\\n The target z/OSMF server host name.\\\\n\\\\n --target-management-class | --tmc (string)\\\\n\\\\n The SMS management class to use for the allocation of the target data set.\\\\n\\\\n --target-password | --tpw (string)\\\\n\\\\n The target z/OSMF password, which can be the same as your TSO password.\\\\n\\\\n --target-port | --tp (number)\\\\n\\\\n The target z/OSMF server port.\\\\n\\\\n --target-storage-class | --tsc (string)\\\\n\\\\n The SMS storage class to use for the allocation of the target data set.\\\\n\\\\n --target-token-type | --ttt (string)\\\\n\\\\n The value of the token to pass to the API for the target system.\\\\n\\\\n --target-token-value | --ttv (string)\\\\n\\\\n The type of token to get and use for the API for the target system.\\\\n\\\\n --target-user | --tu (string)\\\\n\\\\n The target z/OSMF user name, which can be the same as your TSO login.\\\\n\\\\n --target-volume-serial | --tvs | --target-volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the target data set to be placed.\\\\n\\\\n --target-zosmf-profile | --t-zosmf-p | --target-zosmf-p (string)\\\\n\\\\n The name of a z/OSMF profile to load for the target host.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET' using the --target-zosmf-p option to specify the target host\\\\n using a zosmf profile:\\\\n\\\\n $ zowe zos-files copy data-set-cross-lpar \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\" --target-zosmf-p SYS1\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set-cross-lpar \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\" --target-zosmf-p SYS1\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set-cross-lpar \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\" --target-zosmf-p SYS1\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set named 'USER.TO.SET' using the --target-host, --target-user, and\\\\n --target-password options:\\\\n\\\\n $ zowe zos-files copy data-set-cross-lpar \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET\\\\\\" --target-host sys1.com --target-user user1 --target-password pass1\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-cross-lpar | dsclp\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Copy a data set to another data set on a specified LPAR\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files copy data-set-cross-lpar [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n fromDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy from\\\\n\\\\n toDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy to. If the dataset does not exist\\\\n it will be allocated automatically\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --replace | --rep (boolean)\\\\n\\\\n Specify this option as true if you wish to replace the target dataset if it\\\\n already exists\\\\n\\\\n --target-data-class | --tdc (string)\\\\n\\\\n The SMS data class to use for the allocation of the target data set.\\\\n\\\\n --target-host | --th (string)\\\\n\\\\n The target z/OSMF server host name.\\\\n\\\\n --target-management-class | --tmc (string)\\\\n\\\\n The SMS management class to use for the allocation of the target data set.\\\\n\\\\n --target-password | --tpw (string)\\\\n\\\\n The target z/OSMF password, which can be the same as your TSO password.\\\\n\\\\n --target-port | --tp (number)\\\\n\\\\n The target z/OSMF server port.\\\\n\\\\n --target-storage-class | --tsc (string)\\\\n\\\\n The SMS storage class to use for the allocation of the target data set.\\\\n\\\\n --target-token-type | --ttt (string)\\\\n\\\\n The value of the token to pass to the API for the target system.\\\\n\\\\n --target-token-value | --ttv (string)\\\\n\\\\n The type of token to get and use for the API for the target system.\\\\n\\\\n --target-user | --tu (string)\\\\n\\\\n The target z/OSMF user name, which can be the same as your TSO login.\\\\n\\\\n --target-volume-serial | --tvs | --target-volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the target data set to be placed.\\\\n\\\\n --target-zosmf-profile | --t-zosmf-p | --target-zosmf-p (string)\\\\n\\\\n The name of a z/OSMF profile to load for the target host.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET' using the --target-zosmf-p option to specify the target host\\\\n using a zosmf profile:\\\\n\\\\n $ zowe zos-files copy data-set-cross-lpar \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\" --target-zosmf-p SYS1\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set-cross-lpar \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\" --target-zosmf-p SYS1\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set-cross-lpar \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\" --target-zosmf-p SYS1\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set named 'USER.TO.SET' using the --target-host, --target-user, and\\\\n --target-password options:\\\\n\\\\n $ zowe zos-files copy data-set-cross-lpar \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET\\\\\\" --target-host sys1.com --target-user user1 --target-password pass1\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-cross-lpar | dsclp\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Copy a data set to another data set on a specified LPAR.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files copy data-set-cross-lpar [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n fromDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy from\\\\n\\\\n toDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy to. If the data set does not\\\\n exist it will be allocated automatically\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --replace | --rep (boolean)\\\\n\\\\n Specify this option as true if you wish to replace the target data set if it\\\\n already exists.\\\\n\\\\n --target-data-class | --tdc (string)\\\\n\\\\n The SMS data class to use for the allocation of the target data set.\\\\n\\\\n --target-host | --th (string)\\\\n\\\\n The target z/OSMF server host name.\\\\n\\\\n --target-management-class | --tmc (string)\\\\n\\\\n The SMS management class to use for the allocation of the target data set.\\\\n\\\\n --target-password | --tpw (string)\\\\n\\\\n The target z/OSMF password, which can be the same as your TSO password.\\\\n\\\\n --target-port | --tp (number)\\\\n\\\\n The target z/OSMF server port.\\\\n\\\\n --target-storage-class | --tsc (string)\\\\n\\\\n The SMS storage class to use for the allocation of the target data set.\\\\n\\\\n --target-token-type | --ttt (string)\\\\n\\\\n The value of the token to pass to the API for the target system.\\\\n\\\\n --target-token-value | --ttv (string)\\\\n\\\\n The type of token to get and use for the API for the target system.\\\\n\\\\n --target-user | --tu (string)\\\\n\\\\n The target z/OSMF user name, which can be the same as your TSO login.\\\\n\\\\n --target-volume-serial | --tvs | --target-volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the target data set to be placed.\\\\n\\\\n --target-zosmf-profile | --t-zosmf-p | --target-zosmf-p (string)\\\\n\\\\n The name of a z/OSMF profile to load for the target host.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET' using the --target-zosmf-p option to specify the target host\\\\n using a zosmf profile:\\\\n\\\\n $ zowe zos-files copy data-set-cross-lpar \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\" --target-zosmf-p SYS1\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set-cross-lpar \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\" --target-zosmf-p SYS1\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set-cross-lpar \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\" --target-zosmf-p SYS1\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set named 'USER.TO.SET' using the --target-host, --target-user, and\\\\n --target-password options:\\\\n\\\\n $ zowe zos-files copy data-set-cross-lpar \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET\\\\\\" --target-host sys1.com --target-user user1 --target-password pass1\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/create/binaryPds/__snapshots__/cli.files.create.dataset.binary.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/create/binaryPds/__snapshots__/cli.files.create.dataset.binary.integration.test.ts.snap index be73225861..d45b66effb 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/create/binaryPds/__snapshots__/cli.files.create.dataset.binary.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/create/binaryPds/__snapshots__/cli.files.create.dataset.binary.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Create Binary Data Set should display the help 1`] = ` DESCRIPTION ----------- - Create executable data sets + Create executable data sets. USAGE ----- @@ -210,8 +210,8 @@ exports[`Create Binary Data Set should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: data-set-binary.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-binary | bin\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create executable data sets\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-binary [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to create\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --block-size | --bs | --blksize (number)\\\\n\\\\n The block size for the data set (for example, 6160)\\\\n\\\\n Default value: 27998\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --data-set-type | --dst | --dsntype (string)\\\\n\\\\n The data set type (BASIC, EXTPREF, EXTREQ, HFS, LARGE, PDS, LIBRARY, PIPE)\\\\n\\\\n --device-type | --dt | --unit (string)\\\\n\\\\n The device type, also known as 'unit'\\\\n\\\\n --directory-blocks | --db | --dirblks (number)\\\\n\\\\n The number of directory blocks (for example, 25)\\\\n\\\\n Default value: 25\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --primary-space | --ps (number)\\\\n\\\\n The primary space allocation (for example, 5)\\\\n\\\\n Default value: 10\\\\n\\\\n --record-format | --rf | --recfm (string)\\\\n\\\\n The record format for the data set (for example, FB for \\\\\\"Fixed Block\\\\\\")\\\\n\\\\n Default value: U\\\\n\\\\n --record-length | --rl | --lrecl (number)\\\\n\\\\n The logical record length. Analogous to the length of a line (for example, 80)\\\\n\\\\n Default value: 27998\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The secondary space allocation (for example, 1)\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The size of the data set (specified as nCYL or nTRK - where n is the number of\\\\n cylinders or tracks). Sets the primary allocation (the secondary allocation\\\\n becomes ~10% of the primary).\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volume-serial | --vs | --volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the data set to be placed. A VOLSER\\\\n is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create an empty binary partitioned data set (PDS) with\\\\n default parameters:\\\\n\\\\n $ zowe zos-files create data-set-binary NEW.BINARY.DATASET\\\\n\\\\n - Create an empty binary PDSE using data set type LIBRARY:\\\\n\\\\n $ zowe zos-files create data-set-binary NEW.BINARY.DATASET --data-set-type LIBRARY\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-binary | bin\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create executable data sets.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-binary [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to create\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --block-size | --bs | --blksize (number)\\\\n\\\\n The block size for the data set (for example, 6160)\\\\n\\\\n Default value: 27998\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --data-set-type | --dst | --dsntype (string)\\\\n\\\\n The data set type (BASIC, EXTPREF, EXTREQ, HFS, LARGE, PDS, LIBRARY, PIPE)\\\\n\\\\n --device-type | --dt | --unit (string)\\\\n\\\\n The device type, also known as 'unit'\\\\n\\\\n --directory-blocks | --db | --dirblks (number)\\\\n\\\\n The number of directory blocks (for example, 25)\\\\n\\\\n Default value: 25\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --primary-space | --ps (number)\\\\n\\\\n The primary space allocation (for example, 5)\\\\n\\\\n Default value: 10\\\\n\\\\n --record-format | --rf | --recfm (string)\\\\n\\\\n The record format for the data set (for example, FB for \\\\\\"Fixed Block\\\\\\")\\\\n\\\\n Default value: U\\\\n\\\\n --record-length | --rl | --lrecl (number)\\\\n\\\\n The logical record length. Analogous to the length of a line (for example, 80)\\\\n\\\\n Default value: 27998\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The secondary space allocation (for example, 1)\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The size of the data set (specified as nCYL or nTRK - where n is the number of\\\\n cylinders or tracks). Sets the primary allocation (the secondary allocation\\\\n becomes ~10% of the primary).\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volume-serial | --vs | --volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the data set to be placed. A VOLSER\\\\n is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create an empty binary partitioned data set (PDS) with\\\\n default parameters:\\\\n\\\\n $ zowe zos-files create data-set-binary NEW.BINARY.DATASET\\\\n\\\\n - Create an empty binary PDSE using data set type LIBRARY:\\\\n\\\\n $ zowe zos-files create data-set-binary NEW.BINARY.DATASET --data-set-type LIBRARY\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-binary | bin\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create executable data sets\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-binary [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to create\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --block-size | --bs | --blksize (number)\\\\n\\\\n The block size for the data set (for example, 6160)\\\\n\\\\n Default value: 27998\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --data-set-type | --dst | --dsntype (string)\\\\n\\\\n The data set type (BASIC, EXTPREF, EXTREQ, HFS, LARGE, PDS, LIBRARY, PIPE)\\\\n\\\\n --device-type | --dt | --unit (string)\\\\n\\\\n The device type, also known as 'unit'\\\\n\\\\n --directory-blocks | --db | --dirblks (number)\\\\n\\\\n The number of directory blocks (for example, 25)\\\\n\\\\n Default value: 25\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --primary-space | --ps (number)\\\\n\\\\n The primary space allocation (for example, 5)\\\\n\\\\n Default value: 10\\\\n\\\\n --record-format | --rf | --recfm (string)\\\\n\\\\n The record format for the data set (for example, FB for \\\\\\"Fixed Block\\\\\\")\\\\n\\\\n Default value: U\\\\n\\\\n --record-length | --rl | --lrecl (number)\\\\n\\\\n The logical record length. Analogous to the length of a line (for example, 80)\\\\n\\\\n Default value: 27998\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The secondary space allocation (for example, 1)\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The size of the data set (specified as nCYL or nTRK - where n is the number of\\\\n cylinders or tracks). Sets the primary allocation (the secondary allocation\\\\n becomes ~10% of the primary).\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volume-serial | --vs | --volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the data set to be placed. A VOLSER\\\\n is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create an empty binary partitioned data set (PDS) with\\\\n default parameters:\\\\n\\\\n $ zowe zos-files create data-set-binary NEW.BINARY.DATASET\\\\n\\\\n - Create an empty binary PDSE using data set type LIBRARY:\\\\n\\\\n $ zowe zos-files create data-set-binary NEW.BINARY.DATASET --data-set-type LIBRARY\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-binary | bin\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create executable data sets.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-binary [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to create\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --block-size | --bs | --blksize (number)\\\\n\\\\n The block size for the data set (for example, 6160)\\\\n\\\\n Default value: 27998\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --data-set-type | --dst | --dsntype (string)\\\\n\\\\n The data set type (BASIC, EXTPREF, EXTREQ, HFS, LARGE, PDS, LIBRARY, PIPE)\\\\n\\\\n --device-type | --dt | --unit (string)\\\\n\\\\n The device type, also known as 'unit'\\\\n\\\\n --directory-blocks | --db | --dirblks (number)\\\\n\\\\n The number of directory blocks (for example, 25)\\\\n\\\\n Default value: 25\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --primary-space | --ps (number)\\\\n\\\\n The primary space allocation (for example, 5)\\\\n\\\\n Default value: 10\\\\n\\\\n --record-format | --rf | --recfm (string)\\\\n\\\\n The record format for the data set (for example, FB for \\\\\\"Fixed Block\\\\\\")\\\\n\\\\n Default value: U\\\\n\\\\n --record-length | --rl | --lrecl (number)\\\\n\\\\n The logical record length. Analogous to the length of a line (for example, 80)\\\\n\\\\n Default value: 27998\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The secondary space allocation (for example, 1)\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The size of the data set (specified as nCYL or nTRK - where n is the number of\\\\n cylinders or tracks). Sets the primary allocation (the secondary allocation\\\\n becomes ~10% of the primary).\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volume-serial | --vs | --volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the data set to be placed. A VOLSER\\\\n is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create an empty binary partitioned data set (PDS) with\\\\n default parameters:\\\\n\\\\n $ zowe zos-files create data-set-binary NEW.BINARY.DATASET\\\\n\\\\n - Create an empty binary PDSE using data set type LIBRARY:\\\\n\\\\n $ zowe zos-files create data-set-binary NEW.BINARY.DATASET --data-set-type LIBRARY\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/create/cPds/__snapshots__/cli.files.create.dataset.c.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/create/cPds/__snapshots__/cli.files.create.dataset.c.integration.test.ts.snap index 3e5189ee85..7bbd90d0f9 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/create/cPds/__snapshots__/cli.files.create.dataset.c.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/create/cPds/__snapshots__/cli.files.create.dataset.c.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Create C Data Set should display the help 1`] = ` DESCRIPTION ----------- - Create data sets for C code programming + Create data sets for C code programming. USAGE ----- @@ -209,8 +209,8 @@ exports[`Create C Data Set should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: data-set-c.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-c | dsc\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create data sets for C code programming\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-c [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to create\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --block-size | --bs | --blksize (number)\\\\n\\\\n The block size for the data set (for example, 6160)\\\\n\\\\n Default value: 32760\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --data-set-type | --dst | --dsntype (string)\\\\n\\\\n The data set type (BASIC, EXTPREF, EXTREQ, HFS, LARGE, PDS, LIBRARY, PIPE)\\\\n\\\\n --device-type | --dt | --unit (string)\\\\n\\\\n The device type, also known as 'unit'\\\\n\\\\n --directory-blocks | --db | --dirblks (number)\\\\n\\\\n The number of directory blocks (for example, 25)\\\\n\\\\n Default value: 25\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --primary-space | --ps (number)\\\\n\\\\n The primary space allocation (for example, 5)\\\\n\\\\n Default value: 1\\\\n\\\\n --record-format | --rf | --recfm (string)\\\\n\\\\n The record format for the data set (for example, FB for \\\\\\"Fixed Block\\\\\\")\\\\n\\\\n Default value: VB\\\\n\\\\n --record-length | --rl | --lrecl (number)\\\\n\\\\n The logical record length. Analogous to the length of a line (for example, 80)\\\\n\\\\n Default value: 260\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The secondary space allocation (for example, 1)\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The size of the data set (specified as nCYL or nTRK - where n is the number of\\\\n cylinders or tracks). Sets the primary allocation (the secondary allocation\\\\n becomes ~10% of the primary).\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volume-serial | --vs | --volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the data set to be placed. A VOLSER\\\\n is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create an empty C code PDS with default parameters:\\\\n\\\\n $ zowe zos-files create data-set-c NEW.CCODE.DATASET\\\\n\\\\n - Create an empty C code PDSE using data set type LIBRARY:\\\\n\\\\n $ zowe zos-files create data-set-c NEW.CCODE.DATASET --data-set-type LIBRARY\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-c | dsc\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create data sets for C code programming.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-c [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to create\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --block-size | --bs | --blksize (number)\\\\n\\\\n The block size for the data set (for example, 6160)\\\\n\\\\n Default value: 32760\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --data-set-type | --dst | --dsntype (string)\\\\n\\\\n The data set type (BASIC, EXTPREF, EXTREQ, HFS, LARGE, PDS, LIBRARY, PIPE)\\\\n\\\\n --device-type | --dt | --unit (string)\\\\n\\\\n The device type, also known as 'unit'\\\\n\\\\n --directory-blocks | --db | --dirblks (number)\\\\n\\\\n The number of directory blocks (for example, 25)\\\\n\\\\n Default value: 25\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --primary-space | --ps (number)\\\\n\\\\n The primary space allocation (for example, 5)\\\\n\\\\n Default value: 1\\\\n\\\\n --record-format | --rf | --recfm (string)\\\\n\\\\n The record format for the data set (for example, FB for \\\\\\"Fixed Block\\\\\\")\\\\n\\\\n Default value: VB\\\\n\\\\n --record-length | --rl | --lrecl (number)\\\\n\\\\n The logical record length. Analogous to the length of a line (for example, 80)\\\\n\\\\n Default value: 260\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The secondary space allocation (for example, 1)\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The size of the data set (specified as nCYL or nTRK - where n is the number of\\\\n cylinders or tracks). Sets the primary allocation (the secondary allocation\\\\n becomes ~10% of the primary).\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volume-serial | --vs | --volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the data set to be placed. A VOLSER\\\\n is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create an empty C code PDS with default parameters:\\\\n\\\\n $ zowe zos-files create data-set-c NEW.CCODE.DATASET\\\\n\\\\n - Create an empty C code PDSE using data set type LIBRARY:\\\\n\\\\n $ zowe zos-files create data-set-c NEW.CCODE.DATASET --data-set-type LIBRARY\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-c | dsc\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create data sets for C code programming\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-c [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to create\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --block-size | --bs | --blksize (number)\\\\n\\\\n The block size for the data set (for example, 6160)\\\\n\\\\n Default value: 32760\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --data-set-type | --dst | --dsntype (string)\\\\n\\\\n The data set type (BASIC, EXTPREF, EXTREQ, HFS, LARGE, PDS, LIBRARY, PIPE)\\\\n\\\\n --device-type | --dt | --unit (string)\\\\n\\\\n The device type, also known as 'unit'\\\\n\\\\n --directory-blocks | --db | --dirblks (number)\\\\n\\\\n The number of directory blocks (for example, 25)\\\\n\\\\n Default value: 25\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --primary-space | --ps (number)\\\\n\\\\n The primary space allocation (for example, 5)\\\\n\\\\n Default value: 1\\\\n\\\\n --record-format | --rf | --recfm (string)\\\\n\\\\n The record format for the data set (for example, FB for \\\\\\"Fixed Block\\\\\\")\\\\n\\\\n Default value: VB\\\\n\\\\n --record-length | --rl | --lrecl (number)\\\\n\\\\n The logical record length. Analogous to the length of a line (for example, 80)\\\\n\\\\n Default value: 260\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The secondary space allocation (for example, 1)\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The size of the data set (specified as nCYL or nTRK - where n is the number of\\\\n cylinders or tracks). Sets the primary allocation (the secondary allocation\\\\n becomes ~10% of the primary).\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volume-serial | --vs | --volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the data set to be placed. A VOLSER\\\\n is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create an empty C code PDS with default parameters:\\\\n\\\\n $ zowe zos-files create data-set-c NEW.CCODE.DATASET\\\\n\\\\n - Create an empty C code PDSE using data set type LIBRARY:\\\\n\\\\n $ zowe zos-files create data-set-c NEW.CCODE.DATASET --data-set-type LIBRARY\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-c | dsc\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create data sets for C code programming.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-c [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to create\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --block-size | --bs | --blksize (number)\\\\n\\\\n The block size for the data set (for example, 6160)\\\\n\\\\n Default value: 32760\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --data-set-type | --dst | --dsntype (string)\\\\n\\\\n The data set type (BASIC, EXTPREF, EXTREQ, HFS, LARGE, PDS, LIBRARY, PIPE)\\\\n\\\\n --device-type | --dt | --unit (string)\\\\n\\\\n The device type, also known as 'unit'\\\\n\\\\n --directory-blocks | --db | --dirblks (number)\\\\n\\\\n The number of directory blocks (for example, 25)\\\\n\\\\n Default value: 25\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --primary-space | --ps (number)\\\\n\\\\n The primary space allocation (for example, 5)\\\\n\\\\n Default value: 1\\\\n\\\\n --record-format | --rf | --recfm (string)\\\\n\\\\n The record format for the data set (for example, FB for \\\\\\"Fixed Block\\\\\\")\\\\n\\\\n Default value: VB\\\\n\\\\n --record-length | --rl | --lrecl (number)\\\\n\\\\n The logical record length. Analogous to the length of a line (for example, 80)\\\\n\\\\n Default value: 260\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The secondary space allocation (for example, 1)\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The size of the data set (specified as nCYL or nTRK - where n is the number of\\\\n cylinders or tracks). Sets the primary allocation (the secondary allocation\\\\n becomes ~10% of the primary).\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volume-serial | --vs | --volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the data set to be placed. A VOLSER\\\\n is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create an empty C code PDS with default parameters:\\\\n\\\\n $ zowe zos-files create data-set-c NEW.CCODE.DATASET\\\\n\\\\n - Create an empty C code PDSE using data set type LIBRARY:\\\\n\\\\n $ zowe zos-files create data-set-c NEW.CCODE.DATASET --data-set-type LIBRARY\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/create/classicPds/__snapshots__/cli.files.create.dataset.classic.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/create/classicPds/__snapshots__/cli.files.create.dataset.classic.integration.test.ts.snap index c44823b2de..ae670dfca8 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/create/classicPds/__snapshots__/cli.files.create.dataset.classic.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/create/classicPds/__snapshots__/cli.files.create.dataset.classic.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Create Classic Data Set should display the help 1`] = ` DESCRIPTION ----------- - Create classic data sets (JCL, HLASM, CBL, etc...) + Create classic data sets (JCL, HLASM, CBL, etc...). USAGE ----- @@ -210,8 +210,8 @@ exports[`Create Classic Data Set should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: data-set-classic.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-classic | classic\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create classic data sets (JCL, HLASM, CBL, etc...)\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-classic [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to create\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --block-size | --bs | --blksize (number)\\\\n\\\\n The block size for the data set (for example, 6160)\\\\n\\\\n Default value: 6160\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --data-set-type | --dst | --dsntype (string)\\\\n\\\\n The data set type (BASIC, EXTPREF, EXTREQ, HFS, LARGE, PDS, LIBRARY, PIPE)\\\\n\\\\n --device-type | --dt | --unit (string)\\\\n\\\\n The device type, also known as 'unit'\\\\n\\\\n --directory-blocks | --db | --dirblks (number)\\\\n\\\\n The number of directory blocks (for example, 25)\\\\n\\\\n Default value: 25\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --primary-space | --ps (number)\\\\n\\\\n The primary space allocation (for example, 5)\\\\n\\\\n Default value: 1\\\\n\\\\n --record-format | --rf | --recfm (string)\\\\n\\\\n The record format for the data set (for example, FB for \\\\\\"Fixed Block\\\\\\")\\\\n\\\\n Default value: FB\\\\n\\\\n --record-length | --rl | --lrecl (number)\\\\n\\\\n The logical record length. Analogous to the length of a line (for example, 80)\\\\n\\\\n Default value: 80\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The secondary space allocation (for example, 1)\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The size of the data set (specified as nCYL or nTRK - where n is the number of\\\\n cylinders or tracks). Sets the primary allocation (the secondary allocation\\\\n becomes ~10% of the primary).\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volume-serial | --vs | --volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the data set to be placed. A VOLSER\\\\n is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create an empty z/OS 'classic' PDS with default parameters:\\\\n\\\\n $ zowe zos-files create data-set-classic NEW.CLASSIC.DATASET\\\\n\\\\n - Create an empty z/OS 'classic' PDSE using data set type\\\\n LIBRARY:\\\\n\\\\n $ zowe zos-files create data-set-classic NEW.CLASSIC.DATASET --data-set-type LIBRARY\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-classic | classic\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create classic data sets (JCL, HLASM, CBL, etc...).\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-classic [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to create\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --block-size | --bs | --blksize (number)\\\\n\\\\n The block size for the data set (for example, 6160)\\\\n\\\\n Default value: 6160\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --data-set-type | --dst | --dsntype (string)\\\\n\\\\n The data set type (BASIC, EXTPREF, EXTREQ, HFS, LARGE, PDS, LIBRARY, PIPE)\\\\n\\\\n --device-type | --dt | --unit (string)\\\\n\\\\n The device type, also known as 'unit'\\\\n\\\\n --directory-blocks | --db | --dirblks (number)\\\\n\\\\n The number of directory blocks (for example, 25)\\\\n\\\\n Default value: 25\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --primary-space | --ps (number)\\\\n\\\\n The primary space allocation (for example, 5)\\\\n\\\\n Default value: 1\\\\n\\\\n --record-format | --rf | --recfm (string)\\\\n\\\\n The record format for the data set (for example, FB for \\\\\\"Fixed Block\\\\\\")\\\\n\\\\n Default value: FB\\\\n\\\\n --record-length | --rl | --lrecl (number)\\\\n\\\\n The logical record length. Analogous to the length of a line (for example, 80)\\\\n\\\\n Default value: 80\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The secondary space allocation (for example, 1)\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The size of the data set (specified as nCYL or nTRK - where n is the number of\\\\n cylinders or tracks). Sets the primary allocation (the secondary allocation\\\\n becomes ~10% of the primary).\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volume-serial | --vs | --volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the data set to be placed. A VOLSER\\\\n is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create an empty z/OS 'classic' PDS with default parameters:\\\\n\\\\n $ zowe zos-files create data-set-classic NEW.CLASSIC.DATASET\\\\n\\\\n - Create an empty z/OS 'classic' PDSE using data set type\\\\n LIBRARY:\\\\n\\\\n $ zowe zos-files create data-set-classic NEW.CLASSIC.DATASET --data-set-type LIBRARY\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-classic | classic\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create classic data sets (JCL, HLASM, CBL, etc...)\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-classic [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to create\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --block-size | --bs | --blksize (number)\\\\n\\\\n The block size for the data set (for example, 6160)\\\\n\\\\n Default value: 6160\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --data-set-type | --dst | --dsntype (string)\\\\n\\\\n The data set type (BASIC, EXTPREF, EXTREQ, HFS, LARGE, PDS, LIBRARY, PIPE)\\\\n\\\\n --device-type | --dt | --unit (string)\\\\n\\\\n The device type, also known as 'unit'\\\\n\\\\n --directory-blocks | --db | --dirblks (number)\\\\n\\\\n The number of directory blocks (for example, 25)\\\\n\\\\n Default value: 25\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --primary-space | --ps (number)\\\\n\\\\n The primary space allocation (for example, 5)\\\\n\\\\n Default value: 1\\\\n\\\\n --record-format | --rf | --recfm (string)\\\\n\\\\n The record format for the data set (for example, FB for \\\\\\"Fixed Block\\\\\\")\\\\n\\\\n Default value: FB\\\\n\\\\n --record-length | --rl | --lrecl (number)\\\\n\\\\n The logical record length. Analogous to the length of a line (for example, 80)\\\\n\\\\n Default value: 80\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The secondary space allocation (for example, 1)\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The size of the data set (specified as nCYL or nTRK - where n is the number of\\\\n cylinders or tracks). Sets the primary allocation (the secondary allocation\\\\n becomes ~10% of the primary).\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volume-serial | --vs | --volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the data set to be placed. A VOLSER\\\\n is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create an empty z/OS 'classic' PDS with default parameters:\\\\n\\\\n $ zowe zos-files create data-set-classic NEW.CLASSIC.DATASET\\\\n\\\\n - Create an empty z/OS 'classic' PDSE using data set type\\\\n LIBRARY:\\\\n\\\\n $ zowe zos-files create data-set-classic NEW.CLASSIC.DATASET --data-set-type LIBRARY\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-classic | classic\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create classic data sets (JCL, HLASM, CBL, etc...).\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-classic [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to create\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --block-size | --bs | --blksize (number)\\\\n\\\\n The block size for the data set (for example, 6160)\\\\n\\\\n Default value: 6160\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --data-set-type | --dst | --dsntype (string)\\\\n\\\\n The data set type (BASIC, EXTPREF, EXTREQ, HFS, LARGE, PDS, LIBRARY, PIPE)\\\\n\\\\n --device-type | --dt | --unit (string)\\\\n\\\\n The device type, also known as 'unit'\\\\n\\\\n --directory-blocks | --db | --dirblks (number)\\\\n\\\\n The number of directory blocks (for example, 25)\\\\n\\\\n Default value: 25\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --primary-space | --ps (number)\\\\n\\\\n The primary space allocation (for example, 5)\\\\n\\\\n Default value: 1\\\\n\\\\n --record-format | --rf | --recfm (string)\\\\n\\\\n The record format for the data set (for example, FB for \\\\\\"Fixed Block\\\\\\")\\\\n\\\\n Default value: FB\\\\n\\\\n --record-length | --rl | --lrecl (number)\\\\n\\\\n The logical record length. Analogous to the length of a line (for example, 80)\\\\n\\\\n Default value: 80\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The secondary space allocation (for example, 1)\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The size of the data set (specified as nCYL or nTRK - where n is the number of\\\\n cylinders or tracks). Sets the primary allocation (the secondary allocation\\\\n becomes ~10% of the primary).\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volume-serial | --vs | --volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the data set to be placed. A VOLSER\\\\n is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create an empty z/OS 'classic' PDS with default parameters:\\\\n\\\\n $ zowe zos-files create data-set-classic NEW.CLASSIC.DATASET\\\\n\\\\n - Create an empty z/OS 'classic' PDSE using data set type\\\\n LIBRARY:\\\\n\\\\n $ zowe zos-files create data-set-classic NEW.CLASSIC.DATASET --data-set-type LIBRARY\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/create/ds/__snapshots__/cli.files.create.dataset.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/create/ds/__snapshots__/cli.files.create.dataset.integration.test.ts.snap index bb597a9da4..6239c6d61c 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/create/ds/__snapshots__/cli.files.create.dataset.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/create/ds/__snapshots__/cli.files.create.dataset.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Create Data Set should display the help 1`] = ` DESCRIPTION ----------- - Create data sets based on the properties of an existing data set + Create data sets based on the properties of an existing data set. USAGE ----- diff --git a/packages/cli/__tests__/zosfiles/__integration__/create/ps/__snapshots__/cli.files.create.dataset.ps.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/create/ps/__snapshots__/cli.files.create.dataset.ps.integration.test.ts.snap index b5b486b9ee..0377d79850 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/create/ps/__snapshots__/cli.files.create.dataset.ps.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/create/ps/__snapshots__/cli.files.create.dataset.ps.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Create Physical Sequential Data Set should display the help 1`] = ` DESCRIPTION ----------- - Create physical sequential data sets (PS) + Create physical sequential data sets (PS). USAGE ----- @@ -200,8 +200,8 @@ exports[`Create Physical Sequential Data Set should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: data-set-sequential.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-sequential | ps\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create physical sequential data sets (PS)\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-sequential [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to create\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --block-size | --bs | --blksize (number)\\\\n\\\\n The block size for the data set (for example, 6160)\\\\n\\\\n Default value: 6160\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --device-type | --dt | --unit (string)\\\\n\\\\n The device type, also known as 'unit'\\\\n\\\\n --directory-blocks | --db | --dirblks (number)\\\\n\\\\n The number of directory blocks (for example, 25)\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --primary-space | --ps (number)\\\\n\\\\n The primary space allocation (for example, 5)\\\\n\\\\n Default value: 1\\\\n\\\\n --record-format | --rf | --recfm (string)\\\\n\\\\n The record format for the data set (for example, FB for \\\\\\"Fixed Block\\\\\\")\\\\n\\\\n Default value: FB\\\\n\\\\n --record-length | --rl | --lrecl (number)\\\\n\\\\n The logical record length. Analogous to the length of a line (for example, 80)\\\\n\\\\n Default value: 80\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The secondary space allocation (for example, 1)\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The size of the data set (specified as nCYL or nTRK - where n is the number of\\\\n cylinders or tracks). Sets the primary allocation (the secondary allocation\\\\n becomes ~10% of the primary).\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volume-serial | --vs | --volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the data set to be placed. A VOLSER\\\\n is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create an empty physical sequential data set with default\\\\n parameters:\\\\n\\\\n $ zowe zos-files create data-set-sequential NEW.PS.DATASET\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-sequential | ps\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create physical sequential data sets (PS).\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-sequential [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to create\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --block-size | --bs | --blksize (number)\\\\n\\\\n The block size for the data set (for example, 6160)\\\\n\\\\n Default value: 6160\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --device-type | --dt | --unit (string)\\\\n\\\\n The device type, also known as 'unit'\\\\n\\\\n --directory-blocks | --db | --dirblks (number)\\\\n\\\\n The number of directory blocks (for example, 25)\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --primary-space | --ps (number)\\\\n\\\\n The primary space allocation (for example, 5)\\\\n\\\\n Default value: 1\\\\n\\\\n --record-format | --rf | --recfm (string)\\\\n\\\\n The record format for the data set (for example, FB for \\\\\\"Fixed Block\\\\\\")\\\\n\\\\n Default value: FB\\\\n\\\\n --record-length | --rl | --lrecl (number)\\\\n\\\\n The logical record length. Analogous to the length of a line (for example, 80)\\\\n\\\\n Default value: 80\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The secondary space allocation (for example, 1)\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The size of the data set (specified as nCYL or nTRK - where n is the number of\\\\n cylinders or tracks). Sets the primary allocation (the secondary allocation\\\\n becomes ~10% of the primary).\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volume-serial | --vs | --volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the data set to be placed. A VOLSER\\\\n is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create an empty physical sequential data set with default\\\\n parameters:\\\\n\\\\n $ zowe zos-files create data-set-sequential NEW.PS.DATASET\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-sequential | ps\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create physical sequential data sets (PS)\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-sequential [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to create\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --block-size | --bs | --blksize (number)\\\\n\\\\n The block size for the data set (for example, 6160)\\\\n\\\\n Default value: 6160\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --device-type | --dt | --unit (string)\\\\n\\\\n The device type, also known as 'unit'\\\\n\\\\n --directory-blocks | --db | --dirblks (number)\\\\n\\\\n The number of directory blocks (for example, 25)\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --primary-space | --ps (number)\\\\n\\\\n The primary space allocation (for example, 5)\\\\n\\\\n Default value: 1\\\\n\\\\n --record-format | --rf | --recfm (string)\\\\n\\\\n The record format for the data set (for example, FB for \\\\\\"Fixed Block\\\\\\")\\\\n\\\\n Default value: FB\\\\n\\\\n --record-length | --rl | --lrecl (number)\\\\n\\\\n The logical record length. Analogous to the length of a line (for example, 80)\\\\n\\\\n Default value: 80\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The secondary space allocation (for example, 1)\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The size of the data set (specified as nCYL or nTRK - where n is the number of\\\\n cylinders or tracks). Sets the primary allocation (the secondary allocation\\\\n becomes ~10% of the primary).\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volume-serial | --vs | --volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the data set to be placed. A VOLSER\\\\n is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create an empty physical sequential data set with default\\\\n parameters:\\\\n\\\\n $ zowe zos-files create data-set-sequential NEW.PS.DATASET\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-sequential | ps\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create physical sequential data sets (PS).\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-sequential [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to create\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --block-size | --bs | --blksize (number)\\\\n\\\\n The block size for the data set (for example, 6160)\\\\n\\\\n Default value: 6160\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --device-type | --dt | --unit (string)\\\\n\\\\n The device type, also known as 'unit'\\\\n\\\\n --directory-blocks | --db | --dirblks (number)\\\\n\\\\n The number of directory blocks (for example, 25)\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --primary-space | --ps (number)\\\\n\\\\n The primary space allocation (for example, 5)\\\\n\\\\n Default value: 1\\\\n\\\\n --record-format | --rf | --recfm (string)\\\\n\\\\n The record format for the data set (for example, FB for \\\\\\"Fixed Block\\\\\\")\\\\n\\\\n Default value: FB\\\\n\\\\n --record-length | --rl | --lrecl (number)\\\\n\\\\n The logical record length. Analogous to the length of a line (for example, 80)\\\\n\\\\n Default value: 80\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The secondary space allocation (for example, 1)\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The size of the data set (specified as nCYL or nTRK - where n is the number of\\\\n cylinders or tracks). Sets the primary allocation (the secondary allocation\\\\n becomes ~10% of the primary).\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volume-serial | --vs | --volser (string)\\\\n\\\\n The volume serial (VOLSER) on which you want the data set to be placed. A VOLSER\\\\n is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create an empty physical sequential data set with default\\\\n parameters:\\\\n\\\\n $ zowe zos-files create data-set-sequential NEW.PS.DATASET\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/create/vsam/__snapshots__/cli.files.create.dataset.vsam.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/create/vsam/__snapshots__/cli.files.create.dataset.vsam.integration.test.ts.snap index acb5a0fb0e..05ea885e85 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/create/vsam/__snapshots__/cli.files.create.dataset.vsam.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/create/vsam/__snapshots__/cli.files.create.dataset.vsam.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Create VSAM Data Set should display the help 1`] = ` DESCRIPTION ----------- - Create a VSAM cluster + Create a VSAM cluster. USAGE ----- @@ -23,7 +23,7 @@ exports[`Create VSAM Data Set should display the help 1`] = ` dataSetName (string) - The name of the dataset in which to create a VSAM cluster + The name of the data set in which to create a VSAM cluster OPTIONS ------- @@ -207,8 +207,8 @@ exports[`Create VSAM Data Set should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: data-set-vsam.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-vsam | vsam\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create a VSAM cluster\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-vsam [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the dataset in which to create a VSAM cluster\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --data-set-organization | --dso | --dsorg (string)\\\\n\\\\n The data set organization.\\\\n\\\\n Default value: INDEXED\\\\n Allowed values: INDEXED, IXD, LINEAR, LIN, NONINDEXED, NIXD, NUMBERED, NUMD, ZFS\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --retain-for | --rf (number)\\\\n\\\\n The number of days that the VSAM cluster will be retained on the system. You can\\\\n delete the cluster at any time when neither retain-for nor retain-to is\\\\n specified.\\\\n\\\\n --retain-to | --rt (string)\\\\n\\\\n The earliest date that a command without the PURGE parameter can delete an\\\\n entry. Specify the expiration date in the form yyyyddd, where yyyy is a\\\\n four-digit year (maximum value: 2155) and ddd is the three-digit day of the year\\\\n from 001 through 365 (for non-leap years) or 366 (for leap years). You can\\\\n delete the cluster at any time when neither retain-for nor retain-to is used.\\\\n You cannot specify both the 'retain-to' and 'retain-for' options.\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The number of items for the secondary space allocation (for example, 840). The\\\\n type of item allocated is the same as the type used for the '--size' option. If\\\\n you do not specify a secondary allocation, a value of ~10% of the primary\\\\n allocation is used.\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The primary size to allocate for the VSAM cluster. Specify size as the number of\\\\n items to allocate (nItems). You specify the type of item by keyword.\\\\n\\\\n Default value: 840KB\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volumes | -v (string)\\\\n\\\\n The storage volumes on which to allocate a VSAM cluster. Specify a single volume\\\\n by its volume serial (VOLSER). To specify more than one volume, enclose the\\\\n option in double-quotes and separate each VOLSER with a space. You must specify\\\\n the volumes option when your cluster is not SMS-managed.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create a VSAM data set named \\\\\\"SOME.DATA.SET.NAME\\\\\\" using\\\\n default values of INDEXED, 840 KB primary storage and 84 KB secondary storage:\\\\n\\\\n $ zowe zos-files create data-set-vsam SOME.DATA.SET.NAME\\\\n\\\\n - Create a 5 MB LINEAR VSAM data set named\\\\n \\\\\\"SOME.DATA.SET.NAME\\\\\\" with 1 MB of secondary space. Show the properties of the\\\\n data set when it is created:\\\\n\\\\n $ zowe zos-files create data-set-vsam SOME.DATA.SET.NAME --data-set-organization LINEAR --size 5MB --secondary-space 1 --attributes\\\\n\\\\n - Create a VSAM data set named \\\\\\"SOME.DATA.SET.NAME\\\\\\", which is\\\\n retained for 100 days:\\\\n\\\\n $ zowe zos-files create data-set-vsam SOME.DATA.SET.NAME --retain-for 100 \\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-vsam | vsam\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create a VSAM cluster.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-vsam [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set in which to create a VSAM cluster\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --data-set-organization | --dso | --dsorg (string)\\\\n\\\\n The data set organization.\\\\n\\\\n Default value: INDEXED\\\\n Allowed values: INDEXED, IXD, LINEAR, LIN, NONINDEXED, NIXD, NUMBERED, NUMD, ZFS\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --retain-for | --rf (number)\\\\n\\\\n The number of days that the VSAM cluster will be retained on the system. You can\\\\n delete the cluster at any time when neither retain-for nor retain-to is\\\\n specified.\\\\n\\\\n --retain-to | --rt (string)\\\\n\\\\n The earliest date that a command without the PURGE parameter can delete an\\\\n entry. Specify the expiration date in the form yyyyddd, where yyyy is a\\\\n four-digit year (maximum value: 2155) and ddd is the three-digit day of the year\\\\n from 001 through 365 (for non-leap years) or 366 (for leap years). You can\\\\n delete the cluster at any time when neither retain-for nor retain-to is used.\\\\n You cannot specify both the 'retain-to' and 'retain-for' options.\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The number of items for the secondary space allocation (for example, 840). The\\\\n type of item allocated is the same as the type used for the '--size' option. If\\\\n you do not specify a secondary allocation, a value of ~10% of the primary\\\\n allocation is used.\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The primary size to allocate for the VSAM cluster. Specify size as the number of\\\\n items to allocate (nItems). You specify the type of item by keyword.\\\\n\\\\n Default value: 840KB\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volumes | -v (string)\\\\n\\\\n The storage volumes on which to allocate a VSAM cluster. Specify a single volume\\\\n by its volume serial (VOLSER). To specify more than one volume, enclose the\\\\n option in double-quotes and separate each VOLSER with a space. You must specify\\\\n the volumes option when your cluster is not SMS-managed.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create a VSAM data set named \\\\\\"SOME.DATA.SET.NAME\\\\\\" using\\\\n default values of INDEXED, 840 KB primary storage and 84 KB secondary storage:\\\\n\\\\n $ zowe zos-files create data-set-vsam SOME.DATA.SET.NAME\\\\n\\\\n - Create a 5 MB LINEAR VSAM data set named\\\\n \\\\\\"SOME.DATA.SET.NAME\\\\\\" with 1 MB of secondary space. Show the properties of the\\\\n data set when it is created:\\\\n\\\\n $ zowe zos-files create data-set-vsam SOME.DATA.SET.NAME --data-set-organization LINEAR --size 5MB --secondary-space 1 --attributes\\\\n\\\\n - Create a VSAM data set named \\\\\\"SOME.DATA.SET.NAME\\\\\\", which is\\\\n retained for 100 days:\\\\n\\\\n $ zowe zos-files create data-set-vsam SOME.DATA.SET.NAME --retain-for 100 \\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-vsam | vsam\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create a VSAM cluster\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-vsam [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the dataset in which to create a VSAM cluster\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --data-set-organization | --dso | --dsorg (string)\\\\n\\\\n The data set organization.\\\\n\\\\n Default value: INDEXED\\\\n Allowed values: INDEXED, IXD, LINEAR, LIN, NONINDEXED, NIXD, NUMBERED, NUMD, ZFS\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --retain-for | --rf (number)\\\\n\\\\n The number of days that the VSAM cluster will be retained on the system. You can\\\\n delete the cluster at any time when neither retain-for nor retain-to is\\\\n specified.\\\\n\\\\n --retain-to | --rt (string)\\\\n\\\\n The earliest date that a command without the PURGE parameter can delete an\\\\n entry. Specify the expiration date in the form yyyyddd, where yyyy is a\\\\n four-digit year (maximum value: 2155) and ddd is the three-digit day of the year\\\\n from 001 through 365 (for non-leap years) or 366 (for leap years). You can\\\\n delete the cluster at any time when neither retain-for nor retain-to is used.\\\\n You cannot specify both the 'retain-to' and 'retain-for' options.\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The number of items for the secondary space allocation (for example, 840). The\\\\n type of item allocated is the same as the type used for the '--size' option. If\\\\n you do not specify a secondary allocation, a value of ~10% of the primary\\\\n allocation is used.\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The primary size to allocate for the VSAM cluster. Specify size as the number of\\\\n items to allocate (nItems). You specify the type of item by keyword.\\\\n\\\\n Default value: 840KB\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volumes | -v (string)\\\\n\\\\n The storage volumes on which to allocate a VSAM cluster. Specify a single volume\\\\n by its volume serial (VOLSER). To specify more than one volume, enclose the\\\\n option in double-quotes and separate each VOLSER with a space. You must specify\\\\n the volumes option when your cluster is not SMS-managed.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create a VSAM data set named \\\\\\"SOME.DATA.SET.NAME\\\\\\" using\\\\n default values of INDEXED, 840 KB primary storage and 84 KB secondary storage:\\\\n\\\\n $ zowe zos-files create data-set-vsam SOME.DATA.SET.NAME\\\\n\\\\n - Create a 5 MB LINEAR VSAM data set named\\\\n \\\\\\"SOME.DATA.SET.NAME\\\\\\" with 1 MB of secondary space. Show the properties of the\\\\n data set when it is created:\\\\n\\\\n $ zowe zos-files create data-set-vsam SOME.DATA.SET.NAME --data-set-organization LINEAR --size 5MB --secondary-space 1 --attributes\\\\n\\\\n - Create a VSAM data set named \\\\\\"SOME.DATA.SET.NAME\\\\\\", which is\\\\n retained for 100 days:\\\\n\\\\n $ zowe zos-files create data-set-vsam SOME.DATA.SET.NAME --retain-for 100 \\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-vsam | vsam\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Create a VSAM cluster.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files create data-set-vsam [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set in which to create a VSAM cluster\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Show the full allocation attributes\\\\n\\\\n --data-class | --dc (string)\\\\n\\\\n The SMS data class to use for the allocation\\\\n\\\\n --data-set-organization | --dso | --dsorg (string)\\\\n\\\\n The data set organization.\\\\n\\\\n Default value: INDEXED\\\\n Allowed values: INDEXED, IXD, LINEAR, LIN, NONINDEXED, NIXD, NUMBERED, NUMD, ZFS\\\\n\\\\n --management-class | --mc (string)\\\\n\\\\n The SMS management class to use for the allocation\\\\n\\\\n --retain-for | --rf (number)\\\\n\\\\n The number of days that the VSAM cluster will be retained on the system. You can\\\\n delete the cluster at any time when neither retain-for nor retain-to is\\\\n specified.\\\\n\\\\n --retain-to | --rt (string)\\\\n\\\\n The earliest date that a command without the PURGE parameter can delete an\\\\n entry. Specify the expiration date in the form yyyyddd, where yyyy is a\\\\n four-digit year (maximum value: 2155) and ddd is the three-digit day of the year\\\\n from 001 through 365 (for non-leap years) or 366 (for leap years). You can\\\\n delete the cluster at any time when neither retain-for nor retain-to is used.\\\\n You cannot specify both the 'retain-to' and 'retain-for' options.\\\\n\\\\n --secondary-space | --ss (number)\\\\n\\\\n The number of items for the secondary space allocation (for example, 840). The\\\\n type of item allocated is the same as the type used for the '--size' option. If\\\\n you do not specify a secondary allocation, a value of ~10% of the primary\\\\n allocation is used.\\\\n\\\\n --size | --sz (string)\\\\n\\\\n The primary size to allocate for the VSAM cluster. Specify size as the number of\\\\n items to allocate (nItems). You specify the type of item by keyword.\\\\n\\\\n Default value: 840KB\\\\n\\\\n --storage-class | --sc (string)\\\\n\\\\n The SMS storage class to use for the allocation\\\\n\\\\n --volumes | -v (string)\\\\n\\\\n The storage volumes on which to allocate a VSAM cluster. Specify a single volume\\\\n by its volume serial (VOLSER). To specify more than one volume, enclose the\\\\n option in double-quotes and separate each VOLSER with a space. You must specify\\\\n the volumes option when your cluster is not SMS-managed.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Create a VSAM data set named \\\\\\"SOME.DATA.SET.NAME\\\\\\" using\\\\n default values of INDEXED, 840 KB primary storage and 84 KB secondary storage:\\\\n\\\\n $ zowe zos-files create data-set-vsam SOME.DATA.SET.NAME\\\\n\\\\n - Create a 5 MB LINEAR VSAM data set named\\\\n \\\\\\"SOME.DATA.SET.NAME\\\\\\" with 1 MB of secondary space. Show the properties of the\\\\n data set when it is created:\\\\n\\\\n $ zowe zos-files create data-set-vsam SOME.DATA.SET.NAME --data-set-organization LINEAR --size 5MB --secondary-space 1 --attributes\\\\n\\\\n - Create a VSAM data set named \\\\\\"SOME.DATA.SET.NAME\\\\\\", which is\\\\n retained for 100 days:\\\\n\\\\n $ zowe zos-files create data-set-vsam SOME.DATA.SET.NAME --retain-for 100 \\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/delete/ds/__snapshots__/cli.files.delete.ds.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/delete/ds/__snapshots__/cli.files.delete.ds.integration.test.ts.snap index a76639ec83..52ad2259ab 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/delete/ds/__snapshots__/cli.files.delete.ds.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/delete/ds/__snapshots__/cli.files.delete.ds.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Delete Data Set should display the help 1`] = ` DESCRIPTION ----------- - Delete a data set or data set member permanently + Delete a data set or data set member permanently. USAGE ----- @@ -152,8 +152,8 @@ exports[`Delete Data Set should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: data-set.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete a data set or data set member permanently\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files delete data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to delete\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --for-sure | -f (boolean)\\\\n\\\\n Specify this option to confirm that you want to delete the data set permanently.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --volume | --vol (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. The option is required\\\\n only when the data set is not catalogued on the system.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete the data set named 'ibmuser.cntl':\\\\n\\\\n $ zowe zos-files delete data-set \\\\\\"ibmuser.cntl\\\\\\" -f\\\\n\\\\n - Delete the data set member named 'ibmuser.cntl(mem)':\\\\n\\\\n $ zowe zos-files delete data-set \\\\\\"ibmuser.cntl(mem)\\\\\\" -f\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete a data set or data set member permanently.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files delete data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to delete\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --for-sure | -f (boolean)\\\\n\\\\n Specify this option to confirm that you want to delete the data set permanently.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --volume | --vol (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. The option is required\\\\n only when the data set is not catalogued on the system.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete the data set named 'ibmuser.cntl':\\\\n\\\\n $ zowe zos-files delete data-set \\\\\\"ibmuser.cntl\\\\\\" -f\\\\n\\\\n - Delete the data set member named 'ibmuser.cntl(mem)':\\\\n\\\\n $ zowe zos-files delete data-set \\\\\\"ibmuser.cntl(mem)\\\\\\" -f\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete a data set or data set member permanently\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files delete data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to delete\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --for-sure | -f (boolean)\\\\n\\\\n Specify this option to confirm that you want to delete the data set permanently.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --volume | --vol (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. The option is required\\\\n only when the data set is not catalogued on the system.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete the data set named 'ibmuser.cntl':\\\\n\\\\n $ zowe zos-files delete data-set \\\\\\"ibmuser.cntl\\\\\\" -f\\\\n\\\\n - Delete the data set member named 'ibmuser.cntl(mem)':\\\\n\\\\n $ zowe zos-files delete data-set \\\\\\"ibmuser.cntl(mem)\\\\\\" -f\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete a data set or data set member permanently.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files delete data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to delete\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --for-sure | -f (boolean)\\\\n\\\\n Specify this option to confirm that you want to delete the data set permanently.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --volume | --vol (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. The option is required\\\\n only when the data set is not catalogued on the system.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete the data set named 'ibmuser.cntl':\\\\n\\\\n $ zowe zos-files delete data-set \\\\\\"ibmuser.cntl\\\\\\" -f\\\\n\\\\n - Delete the data set member named 'ibmuser.cntl(mem)':\\\\n\\\\n $ zowe zos-files delete data-set \\\\\\"ibmuser.cntl(mem)\\\\\\" -f\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/delete/uss/__snapshots__/cli.files.delete.uss.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/delete/uss/__snapshots__/cli.files.delete.uss.integration.test.ts.snap index 7306067258..562158c9b3 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/delete/uss/__snapshots__/cli.files.delete.uss.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/delete/uss/__snapshots__/cli.files.delete.uss.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Delete USS File should display the help 1`] = ` DESCRIPTION ----------- - Delete a Unix Systems Services (USS) File or directory permanently + Delete a Unix Systems Services (USS) file or directory permanently. USAGE ----- @@ -157,8 +157,8 @@ exports[`Delete USS File should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: uss-file.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-file | uf | uss\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete a Unix Systems Services (USS) File or directory permanently\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files delete uss-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n fileName\\\\t\\\\t (string)\\\\n\\\\n The name of the file or directory that you want to delete\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --for-sure | -f (boolean)\\\\n\\\\n Specify this option to confirm that you want to delete the file or directory\\\\n permanently.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --recursive | -r (boolean)\\\\n\\\\n Delete directories recursively.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete the empty directory '/u/ibmuser/testcases':\\\\n\\\\n $ zowe zos-files delete uss-file \\\\\\"/a/ibmuser/testcases\\\\\\" -f\\\\n\\\\n - Delete the file named '/a/ibmuser/my_text.txt':\\\\n\\\\n $ zowe zos-files delete uss-file \\\\\\"/a/ibmuser/testcases/my_text.txt\\\\\\" -f\\\\n\\\\n - Recursively delete the directory named\\\\n '/u/ibmuser/testcases':\\\\n\\\\n $ zowe zos-files delete uss-file \\\\\\"/a/ibmuser/testcases\\\\\\" -rf\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-file | uf | uss\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete a Unix Systems Services (USS) file or directory permanently.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files delete uss-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n fileName\\\\t\\\\t (string)\\\\n\\\\n The name of the file or directory that you want to delete\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --for-sure | -f (boolean)\\\\n\\\\n Specify this option to confirm that you want to delete the file or directory\\\\n permanently.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --recursive | -r (boolean)\\\\n\\\\n Delete directories recursively.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete the empty directory '/u/ibmuser/testcases':\\\\n\\\\n $ zowe zos-files delete uss-file \\\\\\"/a/ibmuser/testcases\\\\\\" -f\\\\n\\\\n - Delete the file named '/a/ibmuser/my_text.txt':\\\\n\\\\n $ zowe zos-files delete uss-file \\\\\\"/a/ibmuser/testcases/my_text.txt\\\\\\" -f\\\\n\\\\n - Recursively delete the directory named\\\\n '/u/ibmuser/testcases':\\\\n\\\\n $ zowe zos-files delete uss-file \\\\\\"/a/ibmuser/testcases\\\\\\" -rf\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-file | uf | uss\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete a Unix Systems Services (USS) File or directory permanently\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files delete uss-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n fileName\\\\t\\\\t (string)\\\\n\\\\n The name of the file or directory that you want to delete\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --for-sure | -f (boolean)\\\\n\\\\n Specify this option to confirm that you want to delete the file or directory\\\\n permanently.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --recursive | -r (boolean)\\\\n\\\\n Delete directories recursively.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete the empty directory '/u/ibmuser/testcases':\\\\n\\\\n $ zowe zos-files delete uss-file \\\\\\"/a/ibmuser/testcases\\\\\\" -f\\\\n\\\\n - Delete the file named '/a/ibmuser/my_text.txt':\\\\n\\\\n $ zowe zos-files delete uss-file \\\\\\"/a/ibmuser/testcases/my_text.txt\\\\\\" -f\\\\n\\\\n - Recursively delete the directory named\\\\n '/u/ibmuser/testcases':\\\\n\\\\n $ zowe zos-files delete uss-file \\\\\\"/a/ibmuser/testcases\\\\\\" -rf\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-file | uf | uss\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete a Unix Systems Services (USS) file or directory permanently.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files delete uss-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n fileName\\\\t\\\\t (string)\\\\n\\\\n The name of the file or directory that you want to delete\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --for-sure | -f (boolean)\\\\n\\\\n Specify this option to confirm that you want to delete the file or directory\\\\n permanently.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --recursive | -r (boolean)\\\\n\\\\n Delete directories recursively.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete the empty directory '/u/ibmuser/testcases':\\\\n\\\\n $ zowe zos-files delete uss-file \\\\\\"/a/ibmuser/testcases\\\\\\" -f\\\\n\\\\n - Delete the file named '/a/ibmuser/my_text.txt':\\\\n\\\\n $ zowe zos-files delete uss-file \\\\\\"/a/ibmuser/testcases/my_text.txt\\\\\\" -f\\\\n\\\\n - Recursively delete the directory named\\\\n '/u/ibmuser/testcases':\\\\n\\\\n $ zowe zos-files delete uss-file \\\\\\"/a/ibmuser/testcases\\\\\\" -rf\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/delete/vsam/__snapshots__/cli.files.delete.vsam.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/delete/vsam/__snapshots__/cli.files.delete.vsam.integration.test.ts.snap index d95a7b28c3..2d5e2e8ee0 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/delete/vsam/__snapshots__/cli.files.delete.vsam.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/delete/vsam/__snapshots__/cli.files.delete.vsam.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Delete VSAM Data Set should display delete vsam help 1`] = ` DESCRIPTION ----------- - Delete a VSAM cluster permanently + Delete a VSAM cluster permanently. USAGE ----- @@ -174,8 +174,8 @@ exports[`Delete VSAM Data Set should display delete vsam help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: data-set-vsam.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-vsam | vsam\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete a VSAM cluster permanently\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files delete data-set-vsam [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the VSAM cluster that you want to delete\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --erase | -e (boolean)\\\\n\\\\n Specify this option to overwrite the data component for the cluster with binary\\\\n zeros. This option is ignored if the NOERASE attribute was specified when the\\\\n cluster was defined or altered.\\\\n\\\\n Default value: false\\\\n\\\\n --purge | -p (boolean)\\\\n\\\\n Specify this option to delete the VSAM cluster regardless of its retention\\\\n period or date.\\\\n\\\\n Default value: false\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --for-sure | -f (boolean)\\\\n\\\\n Specify this option to confirm that you want to delete the VSAM cluster\\\\n permanently.\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete the VSAM data set named 'ibmuser.cntl.vsam':\\\\n\\\\n $ zowe zos-files delete data-set-vsam \\\\\\"ibmuser.cntl.vsam\\\\\\" -f\\\\n\\\\n - Delete all expired VSAM data sets that match\\\\n 'ibmuser.AAA.**.FFF':\\\\n\\\\n $ zowe zos-files delete data-set-vsam \\\\\\"ibmuser.AAA.**.FFF\\\\\\" -f\\\\n\\\\n - Delete a non-expired VSAM data set named\\\\n 'ibmuser.cntl.vsam':\\\\n\\\\n $ zowe zos-files delete data-set-vsam \\\\\\"ibmuser.cntl.vsam\\\\\\" -f --purge\\\\n\\\\n - Delete an expired VSAM data set named 'ibmuser.cntl.vsam'\\\\n by overwriting the components with zeros:\\\\n\\\\n $ zowe zos-files delete data-set-vsam \\\\\\"ibmuser.cntl.vsam\\\\\\" -f --erase\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-vsam | vsam\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete a VSAM cluster permanently.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files delete data-set-vsam [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the VSAM cluster that you want to delete\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --erase | -e (boolean)\\\\n\\\\n Specify this option to overwrite the data component for the cluster with binary\\\\n zeros. This option is ignored if the NOERASE attribute was specified when the\\\\n cluster was defined or altered.\\\\n\\\\n Default value: false\\\\n\\\\n --purge | -p (boolean)\\\\n\\\\n Specify this option to delete the VSAM cluster regardless of its retention\\\\n period or date.\\\\n\\\\n Default value: false\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --for-sure | -f (boolean)\\\\n\\\\n Specify this option to confirm that you want to delete the VSAM cluster\\\\n permanently.\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete the VSAM data set named 'ibmuser.cntl.vsam':\\\\n\\\\n $ zowe zos-files delete data-set-vsam \\\\\\"ibmuser.cntl.vsam\\\\\\" -f\\\\n\\\\n - Delete all expired VSAM data sets that match\\\\n 'ibmuser.AAA.**.FFF':\\\\n\\\\n $ zowe zos-files delete data-set-vsam \\\\\\"ibmuser.AAA.**.FFF\\\\\\" -f\\\\n\\\\n - Delete a non-expired VSAM data set named\\\\n 'ibmuser.cntl.vsam':\\\\n\\\\n $ zowe zos-files delete data-set-vsam \\\\\\"ibmuser.cntl.vsam\\\\\\" -f --purge\\\\n\\\\n - Delete an expired VSAM data set named 'ibmuser.cntl.vsam'\\\\n by overwriting the components with zeros:\\\\n\\\\n $ zowe zos-files delete data-set-vsam \\\\\\"ibmuser.cntl.vsam\\\\\\" -f --erase\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-vsam | vsam\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete a VSAM cluster permanently\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files delete data-set-vsam [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the VSAM cluster that you want to delete\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --erase | -e (boolean)\\\\n\\\\n Specify this option to overwrite the data component for the cluster with binary\\\\n zeros. This option is ignored if the NOERASE attribute was specified when the\\\\n cluster was defined or altered.\\\\n\\\\n Default value: false\\\\n\\\\n --purge | -p (boolean)\\\\n\\\\n Specify this option to delete the VSAM cluster regardless of its retention\\\\n period or date.\\\\n\\\\n Default value: false\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --for-sure | -f (boolean)\\\\n\\\\n Specify this option to confirm that you want to delete the VSAM cluster\\\\n permanently.\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete the VSAM data set named 'ibmuser.cntl.vsam':\\\\n\\\\n $ zowe zos-files delete data-set-vsam \\\\\\"ibmuser.cntl.vsam\\\\\\" -f\\\\n\\\\n - Delete all expired VSAM data sets that match\\\\n 'ibmuser.AAA.**.FFF':\\\\n\\\\n $ zowe zos-files delete data-set-vsam \\\\\\"ibmuser.AAA.**.FFF\\\\\\" -f\\\\n\\\\n - Delete a non-expired VSAM data set named\\\\n 'ibmuser.cntl.vsam':\\\\n\\\\n $ zowe zos-files delete data-set-vsam \\\\\\"ibmuser.cntl.vsam\\\\\\" -f --purge\\\\n\\\\n - Delete an expired VSAM data set named 'ibmuser.cntl.vsam'\\\\n by overwriting the components with zeros:\\\\n\\\\n $ zowe zos-files delete data-set-vsam \\\\\\"ibmuser.cntl.vsam\\\\\\" -f --erase\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set-vsam | vsam\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete a VSAM cluster permanently.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files delete data-set-vsam [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the VSAM cluster that you want to delete\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --erase | -e (boolean)\\\\n\\\\n Specify this option to overwrite the data component for the cluster with binary\\\\n zeros. This option is ignored if the NOERASE attribute was specified when the\\\\n cluster was defined or altered.\\\\n\\\\n Default value: false\\\\n\\\\n --purge | -p (boolean)\\\\n\\\\n Specify this option to delete the VSAM cluster regardless of its retention\\\\n period or date.\\\\n\\\\n Default value: false\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n REQUIRED OPTIONS\\\\n ----------------\\\\n\\\\n --for-sure | -f (boolean)\\\\n\\\\n Specify this option to confirm that you want to delete the VSAM cluster\\\\n permanently.\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete the VSAM data set named 'ibmuser.cntl.vsam':\\\\n\\\\n $ zowe zos-files delete data-set-vsam \\\\\\"ibmuser.cntl.vsam\\\\\\" -f\\\\n\\\\n - Delete all expired VSAM data sets that match\\\\n 'ibmuser.AAA.**.FFF':\\\\n\\\\n $ zowe zos-files delete data-set-vsam \\\\\\"ibmuser.AAA.**.FFF\\\\\\" -f\\\\n\\\\n - Delete a non-expired VSAM data set named\\\\n 'ibmuser.cntl.vsam':\\\\n\\\\n $ zowe zos-files delete data-set-vsam \\\\\\"ibmuser.cntl.vsam\\\\\\" -f --purge\\\\n\\\\n - Delete an expired VSAM data set named 'ibmuser.cntl.vsam'\\\\n by overwriting the components with zeros:\\\\n\\\\n $ zowe zos-files delete data-set-vsam \\\\\\"ibmuser.cntl.vsam\\\\\\" -f --erase\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/download/am/__snapshots__/cli.files.download.am.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/download/am/__snapshots__/cli.files.download.am.integration.test.ts.snap index 1938d38119..19ff35a710 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/download/am/__snapshots__/cli.files.download.am.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/download/am/__snapshots__/cli.files.download.am.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Download All Member should display the help 1`] = ` DESCRIPTION ----------- - Download all members from a partitioned data set to a local folder + Download all members from a partitioned data set to a local folder. USAGE ----- @@ -54,7 +54,7 @@ exports[`Download All Member should display the help 1`] = ` --fail-fast | --ff (boolean) - Set this option to false to continue downloading dataset members if one or more + Set this option to false to continue downloading data set members if one or more fail. Default value: true @@ -75,7 +75,7 @@ exports[`Download All Member should display the help 1`] = ` --preserve-original-letter-case | --po (boolean) Specifies if the automatically generated directories and files use the original - letter case + letter case. Default value: false @@ -206,8 +206,8 @@ exports[`Download All Member should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: all-members.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n all-members | am\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download all members from a partitioned data set to a local folder\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download all-members [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set from which you want to download members\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --directory | -d (string)\\\\n\\\\n The directory to where you want to save the members. The command creates the\\\\n directory for you when it does not already exist. By default, the command\\\\n creates a folder structure based on the data set qualifiers. For example, the\\\\n data set ibmuser.new.cntl's members are downloaded to ibmuser/new/cntl).\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --extension | -e (string)\\\\n\\\\n Save the local files with a specified file extension. For example, .txt. Or \\\\\\"\\\\\\"\\\\n for no extension. When no extension is specified, .txt is used as the default\\\\n file extension.\\\\n\\\\n --fail-fast | --ff (boolean)\\\\n\\\\n Set this option to false to continue downloading dataset members if one or more\\\\n fail.\\\\n\\\\n Default value: true\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to download\\\\n members. Increasing the value results in faster downloads. However, increasing\\\\n the value increases resource consumption on z/OS and can be prone to errors\\\\n caused by making too many concurrent requests. If the download process\\\\n encounters an error, the following message displays:\\\\n The maximum number of TSO address spaces have been created. When you specify 0,\\\\n Zowe CLI attempts to download all members at once without a maximum number of\\\\n concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --preserve-original-letter-case | --po (boolean)\\\\n\\\\n Specifies if the automatically generated directories and files use the original\\\\n letter case\\\\n\\\\n Default value: false\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Download the file content in record mode, which means that no data conversion is\\\\n performed and the record length is prepended to the data. The data transfer\\\\n process returns each line as-is, without translation. No delimiters are added\\\\n between records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download the members of the data set \\\\\\"ibmuser.loadlib\\\\\\" in\\\\n binary mode to the directory \\\\\\"loadlib/\\\\\\":\\\\n\\\\n $ zowe zos-files download all-members \\\\\\"ibmuser.loadlib\\\\\\" -b -d loadlib\\\\n\\\\n - Download the members of the data set \\\\\\"ibmuser.cntl\\\\\\" in text\\\\n mode to the directory \\\\\\"jcl/\\\\\\":\\\\n\\\\n $ zowe zos-files download all-members \\\\\\"ibmuser.cntl\\\\\\" -d jcl\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n all-members | am\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download all members from a partitioned data set to a local folder.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download all-members [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set from which you want to download members\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --directory | -d (string)\\\\n\\\\n The directory to where you want to save the members. The command creates the\\\\n directory for you when it does not already exist. By default, the command\\\\n creates a folder structure based on the data set qualifiers. For example, the\\\\n data set ibmuser.new.cntl's members are downloaded to ibmuser/new/cntl).\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --extension | -e (string)\\\\n\\\\n Save the local files with a specified file extension. For example, .txt. Or \\\\\\"\\\\\\"\\\\n for no extension. When no extension is specified, .txt is used as the default\\\\n file extension.\\\\n\\\\n --fail-fast | --ff (boolean)\\\\n\\\\n Set this option to false to continue downloading data set members if one or more\\\\n fail.\\\\n\\\\n Default value: true\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to download\\\\n members. Increasing the value results in faster downloads. However, increasing\\\\n the value increases resource consumption on z/OS and can be prone to errors\\\\n caused by making too many concurrent requests. If the download process\\\\n encounters an error, the following message displays:\\\\n The maximum number of TSO address spaces have been created. When you specify 0,\\\\n Zowe CLI attempts to download all members at once without a maximum number of\\\\n concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --preserve-original-letter-case | --po (boolean)\\\\n\\\\n Specifies if the automatically generated directories and files use the original\\\\n letter case.\\\\n\\\\n Default value: false\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Download the file content in record mode, which means that no data conversion is\\\\n performed and the record length is prepended to the data. The data transfer\\\\n process returns each line as-is, without translation. No delimiters are added\\\\n between records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download the members of the data set \\\\\\"ibmuser.loadlib\\\\\\" in\\\\n binary mode to the directory \\\\\\"loadlib/\\\\\\":\\\\n\\\\n $ zowe zos-files download all-members \\\\\\"ibmuser.loadlib\\\\\\" -b -d loadlib\\\\n\\\\n - Download the members of the data set \\\\\\"ibmuser.cntl\\\\\\" in text\\\\n mode to the directory \\\\\\"jcl/\\\\\\":\\\\n\\\\n $ zowe zos-files download all-members \\\\\\"ibmuser.cntl\\\\\\" -d jcl\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n all-members | am\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download all members from a partitioned data set to a local folder\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download all-members [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set from which you want to download members\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --directory | -d (string)\\\\n\\\\n The directory to where you want to save the members. The command creates the\\\\n directory for you when it does not already exist. By default, the command\\\\n creates a folder structure based on the data set qualifiers. For example, the\\\\n data set ibmuser.new.cntl's members are downloaded to ibmuser/new/cntl).\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --extension | -e (string)\\\\n\\\\n Save the local files with a specified file extension. For example, .txt. Or \\\\\\"\\\\\\"\\\\n for no extension. When no extension is specified, .txt is used as the default\\\\n file extension.\\\\n\\\\n --fail-fast | --ff (boolean)\\\\n\\\\n Set this option to false to continue downloading dataset members if one or more\\\\n fail.\\\\n\\\\n Default value: true\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to download\\\\n members. Increasing the value results in faster downloads. However, increasing\\\\n the value increases resource consumption on z/OS and can be prone to errors\\\\n caused by making too many concurrent requests. If the download process\\\\n encounters an error, the following message displays:\\\\n The maximum number of TSO address spaces have been created. When you specify 0,\\\\n Zowe CLI attempts to download all members at once without a maximum number of\\\\n concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --preserve-original-letter-case | --po (boolean)\\\\n\\\\n Specifies if the automatically generated directories and files use the original\\\\n letter case\\\\n\\\\n Default value: false\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Download the file content in record mode, which means that no data conversion is\\\\n performed and the record length is prepended to the data. The data transfer\\\\n process returns each line as-is, without translation. No delimiters are added\\\\n between records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download the members of the data set \\\\\\"ibmuser.loadlib\\\\\\" in\\\\n binary mode to the directory \\\\\\"loadlib/\\\\\\":\\\\n\\\\n $ zowe zos-files download all-members \\\\\\"ibmuser.loadlib\\\\\\" -b -d loadlib\\\\n\\\\n - Download the members of the data set \\\\\\"ibmuser.cntl\\\\\\" in text\\\\n mode to the directory \\\\\\"jcl/\\\\\\":\\\\n\\\\n $ zowe zos-files download all-members \\\\\\"ibmuser.cntl\\\\\\" -d jcl\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n all-members | am\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download all members from a partitioned data set to a local folder.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download all-members [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set from which you want to download members\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --directory | -d (string)\\\\n\\\\n The directory to where you want to save the members. The command creates the\\\\n directory for you when it does not already exist. By default, the command\\\\n creates a folder structure based on the data set qualifiers. For example, the\\\\n data set ibmuser.new.cntl's members are downloaded to ibmuser/new/cntl).\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --extension | -e (string)\\\\n\\\\n Save the local files with a specified file extension. For example, .txt. Or \\\\\\"\\\\\\"\\\\n for no extension. When no extension is specified, .txt is used as the default\\\\n file extension.\\\\n\\\\n --fail-fast | --ff (boolean)\\\\n\\\\n Set this option to false to continue downloading data set members if one or more\\\\n fail.\\\\n\\\\n Default value: true\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to download\\\\n members. Increasing the value results in faster downloads. However, increasing\\\\n the value increases resource consumption on z/OS and can be prone to errors\\\\n caused by making too many concurrent requests. If the download process\\\\n encounters an error, the following message displays:\\\\n The maximum number of TSO address spaces have been created. When you specify 0,\\\\n Zowe CLI attempts to download all members at once without a maximum number of\\\\n concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --preserve-original-letter-case | --po (boolean)\\\\n\\\\n Specifies if the automatically generated directories and files use the original\\\\n letter case.\\\\n\\\\n Default value: false\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Download the file content in record mode, which means that no data conversion is\\\\n performed and the record length is prepended to the data. The data transfer\\\\n process returns each line as-is, without translation. No delimiters are added\\\\n between records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download the members of the data set \\\\\\"ibmuser.loadlib\\\\\\" in\\\\n binary mode to the directory \\\\\\"loadlib/\\\\\\":\\\\n\\\\n $ zowe zos-files download all-members \\\\\\"ibmuser.loadlib\\\\\\" -b -d loadlib\\\\n\\\\n - Download the members of the data set \\\\\\"ibmuser.cntl\\\\\\" in text\\\\n mode to the directory \\\\\\"jcl/\\\\\\":\\\\n\\\\n $ zowe zos-files download all-members \\\\\\"ibmuser.cntl\\\\\\" -d jcl\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/download/ds/__snapshots__/cli.files.download.ds.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/download/ds/__snapshots__/cli.files.download.ds.integration.test.ts.snap index 3493afb3ab..d0b9aa7fe3 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/download/ds/__snapshots__/cli.files.download.ds.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/download/ds/__snapshots__/cli.files.download.ds.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Download Data Set should display the help 1`] = ` DESCRIPTION ----------- - Download content from a z/OS data set to a local file + Download content from a z/OS data set to a local file. USAGE ----- @@ -53,7 +53,7 @@ exports[`Download Data Set should display the help 1`] = ` --preserve-original-letter-case | --po (boolean) Specifies if the automatically generated directories and files use the original - letter case + letter case. Default value: false @@ -179,8 +179,8 @@ exports[`Download Data Set should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: data-set.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download content from a z/OS data set to a local file\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to download\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --extension | -e (string)\\\\n\\\\n Save the local files with a specified file extension. For example, .txt. Or \\\\\\"\\\\\\"\\\\n for no extension. When no extension is specified, .txt is used as the default\\\\n file extension.\\\\n\\\\n --file | -f (string)\\\\n\\\\n The path to the local file where you want to download the content. When you omit\\\\n the option, the command generates a file name automatically for you.\\\\n\\\\n --preserve-original-letter-case | --po (boolean)\\\\n\\\\n Specifies if the automatically generated directories and files use the original\\\\n letter case\\\\n\\\\n Default value: false\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Download the file content in record mode, which means that no data conversion is\\\\n performed and the record length is prepended to the data. The data transfer\\\\n process returns each line as-is, without translation. No delimiters are added\\\\n between records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download the data set \\\\\\"ibmuser.loadlib(main)\\\\\\" in binary\\\\n mode to the local file \\\\\\"main.obj\\\\\\":\\\\n\\\\n $ zowe zos-files download data-set \\\\\\"ibmuser.loadlib(main)\\\\\\" -b -f main.obj\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download content from a z/OS data set to a local file.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to download\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --extension | -e (string)\\\\n\\\\n Save the local files with a specified file extension. For example, .txt. Or \\\\\\"\\\\\\"\\\\n for no extension. When no extension is specified, .txt is used as the default\\\\n file extension.\\\\n\\\\n --file | -f (string)\\\\n\\\\n The path to the local file where you want to download the content. When you omit\\\\n the option, the command generates a file name automatically for you.\\\\n\\\\n --preserve-original-letter-case | --po (boolean)\\\\n\\\\n Specifies if the automatically generated directories and files use the original\\\\n letter case.\\\\n\\\\n Default value: false\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Download the file content in record mode, which means that no data conversion is\\\\n performed and the record length is prepended to the data. The data transfer\\\\n process returns each line as-is, without translation. No delimiters are added\\\\n between records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download the data set \\\\\\"ibmuser.loadlib(main)\\\\\\" in binary\\\\n mode to the local file \\\\\\"main.obj\\\\\\":\\\\n\\\\n $ zowe zos-files download data-set \\\\\\"ibmuser.loadlib(main)\\\\\\" -b -f main.obj\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download content from a z/OS data set to a local file\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to download\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --extension | -e (string)\\\\n\\\\n Save the local files with a specified file extension. For example, .txt. Or \\\\\\"\\\\\\"\\\\n for no extension. When no extension is specified, .txt is used as the default\\\\n file extension.\\\\n\\\\n --file | -f (string)\\\\n\\\\n The path to the local file where you want to download the content. When you omit\\\\n the option, the command generates a file name automatically for you.\\\\n\\\\n --preserve-original-letter-case | --po (boolean)\\\\n\\\\n Specifies if the automatically generated directories and files use the original\\\\n letter case\\\\n\\\\n Default value: false\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Download the file content in record mode, which means that no data conversion is\\\\n performed and the record length is prepended to the data. The data transfer\\\\n process returns each line as-is, without translation. No delimiters are added\\\\n between records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download the data set \\\\\\"ibmuser.loadlib(main)\\\\\\" in binary\\\\n mode to the local file \\\\\\"main.obj\\\\\\":\\\\n\\\\n $ zowe zos-files download data-set \\\\\\"ibmuser.loadlib(main)\\\\\\" -b -f main.obj\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download content from a z/OS data set to a local file.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to download\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --extension | -e (string)\\\\n\\\\n Save the local files with a specified file extension. For example, .txt. Or \\\\\\"\\\\\\"\\\\n for no extension. When no extension is specified, .txt is used as the default\\\\n file extension.\\\\n\\\\n --file | -f (string)\\\\n\\\\n The path to the local file where you want to download the content. When you omit\\\\n the option, the command generates a file name automatically for you.\\\\n\\\\n --preserve-original-letter-case | --po (boolean)\\\\n\\\\n Specifies if the automatically generated directories and files use the original\\\\n letter case.\\\\n\\\\n Default value: false\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Download the file content in record mode, which means that no data conversion is\\\\n performed and the record length is prepended to the data. The data transfer\\\\n process returns each line as-is, without translation. No delimiters are added\\\\n between records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download the data set \\\\\\"ibmuser.loadlib(main)\\\\\\" in binary\\\\n mode to the local file \\\\\\"main.obj\\\\\\":\\\\n\\\\n $ zowe zos-files download data-set \\\\\\"ibmuser.loadlib(main)\\\\\\" -b -f main.obj\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/download/dsm/__snapshots__/cli.files.download.dsm.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/download/dsm/__snapshots__/cli.files.download.dsm.integration.test.ts.snap index e3da90050c..078633f621 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/download/dsm/__snapshots__/cli.files.download.dsm.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/download/dsm/__snapshots__/cli.files.download.dsm.integration.test.ts.snap @@ -34,7 +34,7 @@ exports[`Download Dataset Matching should display the help 1`] = ` **: matches any number of characters within any number of data set name qualifiers (e.g. \\"ibmuser.**.old\\" matches both \\"ibmuser.jcl.old\\" and \\"ibmuser.jcl.very.old\\") - However, the pattern cannot begin with any of these sequences.You can specify + However, the pattern cannot begin with any of these sequences. You can specify multiple patterns separated by commas, for example \\"ibmuser.**.cntl,ibmuser.**.jcl\\" @@ -79,7 +79,7 @@ exports[`Download Dataset Matching should display the help 1`] = ` --fail-fast | --ff (boolean) - Set this option to false to continue downloading dataset members if one or more + Set this option to false to continue downloading data set members if one or more fail. Default value: true @@ -100,7 +100,7 @@ exports[`Download Dataset Matching should display the help 1`] = ` --preserve-original-letter-case | --po (boolean) Specifies if the automatically generated directories and files use the original - letter case + letter case. Default value: false @@ -234,8 +234,8 @@ exports[`Download Dataset Matching should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: data-sets-matching.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-sets-matching | dsm | data-set-matching\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download all data sets that match a DSLEVEL pattern (see help below). You can\\\\n use several options to qualify which data sets will be skipped and how the\\\\n downloaded files will be structured. Data sets that are neither physical\\\\n sequential nor partitioned data sets (with members) will be excluded.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download data-sets-matching [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n pattern\\\\t\\\\t (string)\\\\n\\\\n The pattern or patterns to match data sets against. Also known as 'DSLEVEL'. The\\\\n following special sequences can be used in the pattern:\\\\n %: matches any single character\\\\n *: matches any number of characters within a data set name qualifier (e.g.\\\\n \\\\\\"ibmuser.j*.old\\\\\\" matches \\\\\\"ibmuser.jcl.old\\\\\\" but not \\\\\\"ibmuser.jcl.very.old\\\\\\")\\\\n **: matches any number of characters within any number of data set name\\\\n qualifiers (e.g. \\\\\\"ibmuser.**.old\\\\\\" matches both \\\\\\"ibmuser.jcl.old\\\\\\" and\\\\n \\\\\\"ibmuser.jcl.very.old\\\\\\")\\\\n However, the pattern cannot begin with any of these sequences.You can specify\\\\n multiple patterns separated by commas, for example\\\\n \\\\\\"ibmuser.**.cntl,ibmuser.**.jcl\\\\\\"\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --directory | -d (string)\\\\n\\\\n The directory to where you want to save the members. The command creates the\\\\n directory for you when it does not already exist. By default, the command\\\\n creates a folder structure based on the data set qualifiers. For example, the\\\\n data set ibmuser.new.cntl's members are downloaded to ibmuser/new/cntl).\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --exclude-patterns | --ep (string)\\\\n\\\\n Exclude data sets that match these DSLEVEL patterns. Any data sets that match\\\\n this pattern will not be downloaded.\\\\n\\\\n --extension | -e (string)\\\\n\\\\n Save the local files with a specified file extension. For example, .txt. Or \\\\\\"\\\\\\"\\\\n for no extension. When no extension is specified, .txt is used as the default\\\\n file extension.\\\\n\\\\n --extension-map | --em (string)\\\\n\\\\n Use this option to map data set names that match your pattern to the desired\\\\n extension. A comma delimited key value pairing (e.g. \\\\\\"cntl=.jcl,cpgm=.c\\\\\\" to map\\\\n the last segment of each data set (also known as the \\\\\\"low level qualifier\\\\\\" to\\\\n the desired local file extension).\\\\n\\\\n --fail-fast | --ff (boolean)\\\\n\\\\n Set this option to false to continue downloading dataset members if one or more\\\\n fail.\\\\n\\\\n Default value: true\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to download\\\\n members. Increasing the value results in faster downloads. However, increasing\\\\n the value increases resource consumption on z/OS and can be prone to errors\\\\n caused by making too many concurrent requests. If the download process\\\\n encounters an error, the following message displays:\\\\n The maximum number of TSO address spaces have been created. When you specify 0,\\\\n Zowe CLI attempts to download all members at once without a maximum number of\\\\n concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --preserve-original-letter-case | --po (boolean)\\\\n\\\\n Specifies if the automatically generated directories and files use the original\\\\n letter case\\\\n\\\\n Default value: false\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Download the file content in record mode, which means that no data conversion is\\\\n performed and the record length is prepended to the data. The data transfer\\\\n process returns each line as-is, without translation. No delimiters are added\\\\n between records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download all data sets beginning with \\\\\\"ibmuser\\\\\\" and ending\\\\n with \\\\\\".cntl\\\\\\" or \\\\\\".jcl\\\\\\" to the local directory \\\\\\"jcl\\\\\\" to files with the extension\\\\n \\\\\\".jcl\\\\\\":\\\\n\\\\n $ zowe zos-files download data-sets-matching \\\\\\"ibmuser.**.cntl, ibmuser.**.jcl\\\\\\" --directory jcl --extension .jcl\\\\n\\\\n - Download all data sets that begin with\\\\n \\\\\\"ibmuser.public.project\\\\\\" or \\\\\\"ibmuser.project.private\\\\\\", excluding those that end\\\\n in \\\\\\"lib\\\\\\" to the local directory \\\\\\"project\\\\\\", providing a custom mapping of data\\\\n set low level qualifier to local file extension:\\\\n\\\\n $ zowe zos-files download data-sets-matching \\\\\\"ibmuser.public.project.*, ibmuser.project.private.*\\\\\\" --exclude-patterns \\\\\\"ibmuser.public.**.*lib\\\\\\" --directory project --extension-map cpgm=c,asmpgm=asm,java=java,chdr=c,jcl=jcl,cntl=jcl\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-sets-matching | dsm | data-set-matching\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download all data sets that match a DSLEVEL pattern (see help below). You can\\\\n use several options to qualify which data sets will be skipped and how the\\\\n downloaded files will be structured. Data sets that are neither physical\\\\n sequential nor partitioned data sets (with members) will be excluded.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download data-sets-matching [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n pattern\\\\t\\\\t (string)\\\\n\\\\n The pattern or patterns to match data sets against. Also known as 'DSLEVEL'. The\\\\n following special sequences can be used in the pattern:\\\\n %: matches any single character\\\\n *: matches any number of characters within a data set name qualifier (e.g.\\\\n \\\\\\"ibmuser.j*.old\\\\\\" matches \\\\\\"ibmuser.jcl.old\\\\\\" but not \\\\\\"ibmuser.jcl.very.old\\\\\\")\\\\n **: matches any number of characters within any number of data set name\\\\n qualifiers (e.g. \\\\\\"ibmuser.**.old\\\\\\" matches both \\\\\\"ibmuser.jcl.old\\\\\\" and\\\\n \\\\\\"ibmuser.jcl.very.old\\\\\\")\\\\n However, the pattern cannot begin with any of these sequences. You can specify\\\\n multiple patterns separated by commas, for example\\\\n \\\\\\"ibmuser.**.cntl,ibmuser.**.jcl\\\\\\"\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --directory | -d (string)\\\\n\\\\n The directory to where you want to save the members. The command creates the\\\\n directory for you when it does not already exist. By default, the command\\\\n creates a folder structure based on the data set qualifiers. For example, the\\\\n data set ibmuser.new.cntl's members are downloaded to ibmuser/new/cntl).\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --exclude-patterns | --ep (string)\\\\n\\\\n Exclude data sets that match these DSLEVEL patterns. Any data sets that match\\\\n this pattern will not be downloaded.\\\\n\\\\n --extension | -e (string)\\\\n\\\\n Save the local files with a specified file extension. For example, .txt. Or \\\\\\"\\\\\\"\\\\n for no extension. When no extension is specified, .txt is used as the default\\\\n file extension.\\\\n\\\\n --extension-map | --em (string)\\\\n\\\\n Use this option to map data set names that match your pattern to the desired\\\\n extension. A comma delimited key value pairing (e.g. \\\\\\"cntl=.jcl,cpgm=.c\\\\\\" to map\\\\n the last segment of each data set (also known as the \\\\\\"low level qualifier\\\\\\" to\\\\n the desired local file extension).\\\\n\\\\n --fail-fast | --ff (boolean)\\\\n\\\\n Set this option to false to continue downloading data set members if one or more\\\\n fail.\\\\n\\\\n Default value: true\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to download\\\\n members. Increasing the value results in faster downloads. However, increasing\\\\n the value increases resource consumption on z/OS and can be prone to errors\\\\n caused by making too many concurrent requests. If the download process\\\\n encounters an error, the following message displays:\\\\n The maximum number of TSO address spaces have been created. When you specify 0,\\\\n Zowe CLI attempts to download all members at once without a maximum number of\\\\n concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --preserve-original-letter-case | --po (boolean)\\\\n\\\\n Specifies if the automatically generated directories and files use the original\\\\n letter case.\\\\n\\\\n Default value: false\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Download the file content in record mode, which means that no data conversion is\\\\n performed and the record length is prepended to the data. The data transfer\\\\n process returns each line as-is, without translation. No delimiters are added\\\\n between records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download all data sets beginning with \\\\\\"ibmuser\\\\\\" and ending\\\\n with \\\\\\".cntl\\\\\\" or \\\\\\".jcl\\\\\\" to the local directory \\\\\\"jcl\\\\\\" to files with the extension\\\\n \\\\\\".jcl\\\\\\":\\\\n\\\\n $ zowe zos-files download data-sets-matching \\\\\\"ibmuser.**.cntl, ibmuser.**.jcl\\\\\\" --directory jcl --extension .jcl\\\\n\\\\n - Download all data sets that begin with\\\\n \\\\\\"ibmuser.public.project\\\\\\" or \\\\\\"ibmuser.project.private\\\\\\", excluding those that end\\\\n in \\\\\\"lib\\\\\\" to the local directory \\\\\\"project\\\\\\", providing a custom mapping of data\\\\n set low level qualifier to local file extension:\\\\n\\\\n $ zowe zos-files download data-sets-matching \\\\\\"ibmuser.public.project.*, ibmuser.project.private.*\\\\\\" --exclude-patterns \\\\\\"ibmuser.public.**.*lib\\\\\\" --directory project --extension-map cpgm=c,asmpgm=asm,java=java,chdr=c,jcl=jcl,cntl=jcl\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-sets-matching | dsm | data-set-matching\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download all data sets that match a DSLEVEL pattern (see help below). You can\\\\n use several options to qualify which data sets will be skipped and how the\\\\n downloaded files will be structured. Data sets that are neither physical\\\\n sequential nor partitioned data sets (with members) will be excluded.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download data-sets-matching [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n pattern\\\\t\\\\t (string)\\\\n\\\\n The pattern or patterns to match data sets against. Also known as 'DSLEVEL'. The\\\\n following special sequences can be used in the pattern:\\\\n %: matches any single character\\\\n *: matches any number of characters within a data set name qualifier (e.g.\\\\n \\\\\\"ibmuser.j*.old\\\\\\" matches \\\\\\"ibmuser.jcl.old\\\\\\" but not \\\\\\"ibmuser.jcl.very.old\\\\\\")\\\\n **: matches any number of characters within any number of data set name\\\\n qualifiers (e.g. \\\\\\"ibmuser.**.old\\\\\\" matches both \\\\\\"ibmuser.jcl.old\\\\\\" and\\\\n \\\\\\"ibmuser.jcl.very.old\\\\\\")\\\\n However, the pattern cannot begin with any of these sequences.You can specify\\\\n multiple patterns separated by commas, for example\\\\n \\\\\\"ibmuser.**.cntl,ibmuser.**.jcl\\\\\\"\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --directory | -d (string)\\\\n\\\\n The directory to where you want to save the members. The command creates the\\\\n directory for you when it does not already exist. By default, the command\\\\n creates a folder structure based on the data set qualifiers. For example, the\\\\n data set ibmuser.new.cntl's members are downloaded to ibmuser/new/cntl).\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --exclude-patterns | --ep (string)\\\\n\\\\n Exclude data sets that match these DSLEVEL patterns. Any data sets that match\\\\n this pattern will not be downloaded.\\\\n\\\\n --extension | -e (string)\\\\n\\\\n Save the local files with a specified file extension. For example, .txt. Or \\\\\\"\\\\\\"\\\\n for no extension. When no extension is specified, .txt is used as the default\\\\n file extension.\\\\n\\\\n --extension-map | --em (string)\\\\n\\\\n Use this option to map data set names that match your pattern to the desired\\\\n extension. A comma delimited key value pairing (e.g. \\\\\\"cntl=.jcl,cpgm=.c\\\\\\" to map\\\\n the last segment of each data set (also known as the \\\\\\"low level qualifier\\\\\\" to\\\\n the desired local file extension).\\\\n\\\\n --fail-fast | --ff (boolean)\\\\n\\\\n Set this option to false to continue downloading dataset members if one or more\\\\n fail.\\\\n\\\\n Default value: true\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to download\\\\n members. Increasing the value results in faster downloads. However, increasing\\\\n the value increases resource consumption on z/OS and can be prone to errors\\\\n caused by making too many concurrent requests. If the download process\\\\n encounters an error, the following message displays:\\\\n The maximum number of TSO address spaces have been created. When you specify 0,\\\\n Zowe CLI attempts to download all members at once without a maximum number of\\\\n concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --preserve-original-letter-case | --po (boolean)\\\\n\\\\n Specifies if the automatically generated directories and files use the original\\\\n letter case\\\\n\\\\n Default value: false\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Download the file content in record mode, which means that no data conversion is\\\\n performed and the record length is prepended to the data. The data transfer\\\\n process returns each line as-is, without translation. No delimiters are added\\\\n between records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download all data sets beginning with \\\\\\"ibmuser\\\\\\" and ending\\\\n with \\\\\\".cntl\\\\\\" or \\\\\\".jcl\\\\\\" to the local directory \\\\\\"jcl\\\\\\" to files with the extension\\\\n \\\\\\".jcl\\\\\\":\\\\n\\\\n $ zowe zos-files download data-sets-matching \\\\\\"ibmuser.**.cntl, ibmuser.**.jcl\\\\\\" --directory jcl --extension .jcl\\\\n\\\\n - Download all data sets that begin with\\\\n \\\\\\"ibmuser.public.project\\\\\\" or \\\\\\"ibmuser.project.private\\\\\\", excluding those that end\\\\n in \\\\\\"lib\\\\\\" to the local directory \\\\\\"project\\\\\\", providing a custom mapping of data\\\\n set low level qualifier to local file extension:\\\\n\\\\n $ zowe zos-files download data-sets-matching \\\\\\"ibmuser.public.project.*, ibmuser.project.private.*\\\\\\" --exclude-patterns \\\\\\"ibmuser.public.**.*lib\\\\\\" --directory project --extension-map cpgm=c,asmpgm=asm,java=java,chdr=c,jcl=jcl,cntl=jcl\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-sets-matching | dsm | data-set-matching\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download all data sets that match a DSLEVEL pattern (see help below). You can\\\\n use several options to qualify which data sets will be skipped and how the\\\\n downloaded files will be structured. Data sets that are neither physical\\\\n sequential nor partitioned data sets (with members) will be excluded.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download data-sets-matching [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n pattern\\\\t\\\\t (string)\\\\n\\\\n The pattern or patterns to match data sets against. Also known as 'DSLEVEL'. The\\\\n following special sequences can be used in the pattern:\\\\n %: matches any single character\\\\n *: matches any number of characters within a data set name qualifier (e.g.\\\\n \\\\\\"ibmuser.j*.old\\\\\\" matches \\\\\\"ibmuser.jcl.old\\\\\\" but not \\\\\\"ibmuser.jcl.very.old\\\\\\")\\\\n **: matches any number of characters within any number of data set name\\\\n qualifiers (e.g. \\\\\\"ibmuser.**.old\\\\\\" matches both \\\\\\"ibmuser.jcl.old\\\\\\" and\\\\n \\\\\\"ibmuser.jcl.very.old\\\\\\")\\\\n However, the pattern cannot begin with any of these sequences. You can specify\\\\n multiple patterns separated by commas, for example\\\\n \\\\\\"ibmuser.**.cntl,ibmuser.**.jcl\\\\\\"\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --directory | -d (string)\\\\n\\\\n The directory to where you want to save the members. The command creates the\\\\n directory for you when it does not already exist. By default, the command\\\\n creates a folder structure based on the data set qualifiers. For example, the\\\\n data set ibmuser.new.cntl's members are downloaded to ibmuser/new/cntl).\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --exclude-patterns | --ep (string)\\\\n\\\\n Exclude data sets that match these DSLEVEL patterns. Any data sets that match\\\\n this pattern will not be downloaded.\\\\n\\\\n --extension | -e (string)\\\\n\\\\n Save the local files with a specified file extension. For example, .txt. Or \\\\\\"\\\\\\"\\\\n for no extension. When no extension is specified, .txt is used as the default\\\\n file extension.\\\\n\\\\n --extension-map | --em (string)\\\\n\\\\n Use this option to map data set names that match your pattern to the desired\\\\n extension. A comma delimited key value pairing (e.g. \\\\\\"cntl=.jcl,cpgm=.c\\\\\\" to map\\\\n the last segment of each data set (also known as the \\\\\\"low level qualifier\\\\\\" to\\\\n the desired local file extension).\\\\n\\\\n --fail-fast | --ff (boolean)\\\\n\\\\n Set this option to false to continue downloading data set members if one or more\\\\n fail.\\\\n\\\\n Default value: true\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to download\\\\n members. Increasing the value results in faster downloads. However, increasing\\\\n the value increases resource consumption on z/OS and can be prone to errors\\\\n caused by making too many concurrent requests. If the download process\\\\n encounters an error, the following message displays:\\\\n The maximum number of TSO address spaces have been created. When you specify 0,\\\\n Zowe CLI attempts to download all members at once without a maximum number of\\\\n concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --preserve-original-letter-case | --po (boolean)\\\\n\\\\n Specifies if the automatically generated directories and files use the original\\\\n letter case.\\\\n\\\\n Default value: false\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Download the file content in record mode, which means that no data conversion is\\\\n performed and the record length is prepended to the data. The data transfer\\\\n process returns each line as-is, without translation. No delimiters are added\\\\n between records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download all data sets beginning with \\\\\\"ibmuser\\\\\\" and ending\\\\n with \\\\\\".cntl\\\\\\" or \\\\\\".jcl\\\\\\" to the local directory \\\\\\"jcl\\\\\\" to files with the extension\\\\n \\\\\\".jcl\\\\\\":\\\\n\\\\n $ zowe zos-files download data-sets-matching \\\\\\"ibmuser.**.cntl, ibmuser.**.jcl\\\\\\" --directory jcl --extension .jcl\\\\n\\\\n - Download all data sets that begin with\\\\n \\\\\\"ibmuser.public.project\\\\\\" or \\\\\\"ibmuser.project.private\\\\\\", excluding those that end\\\\n in \\\\\\"lib\\\\\\" to the local directory \\\\\\"project\\\\\\", providing a custom mapping of data\\\\n set low level qualifier to local file extension:\\\\n\\\\n $ zowe zos-files download data-sets-matching \\\\\\"ibmuser.public.project.*, ibmuser.project.private.*\\\\\\" --exclude-patterns \\\\\\"ibmuser.public.**.*lib\\\\\\" --directory project --extension-map cpgm=c,asmpgm=asm,java=java,chdr=c,jcl=jcl,cntl=jcl\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/download/uss/__snapshots__/cli.files.download.uss.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/download/uss/__snapshots__/cli.files.download.uss.integration.test.ts.snap index 80245f68d0..31c18dade7 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/download/uss/__snapshots__/cli.files.download.uss.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/download/uss/__snapshots__/cli.files.download.uss.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Download USS File should display the help 1`] = ` DESCRIPTION ----------- - Download content from a USS file to a local file on your PC + Download content from a USS file to a local file on your PC. USAGE ----- @@ -158,8 +158,8 @@ exports[`Download USS File should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: uss-file.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-file | uf | uss\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download content from a USS file to a local file on your PC\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download uss-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n ussFileName\\\\t\\\\t (string)\\\\n\\\\n The name of the USS file you want to download\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --file | -f (string)\\\\n\\\\n The path to the local file where you want to download the content. When you omit\\\\n the option, the command generates a file name automatically for you.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download the file \\\\\\"/a/ibmuser/my_text.txt\\\\\\" to\\\\n ./my_text.txt:\\\\n\\\\n $ zowe zos-files download uss-file \\\\\\"/a/ibmuser/my_text.txt\\\\\\" -f ./my_text.txt\\\\n\\\\n - Download the file \\\\\\"/a/ibmuser/MyJava.class\\\\\\" to\\\\n \\\\\\"java/MyJava.class\\\\\\" in binary mode:\\\\n\\\\n $ zowe zos-files download uss-file \\\\\\"/a/ibmuser/MyJava.class\\\\\\" -b -f \\\\\\"java/MyJava.class\\\\\\"\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-file | uf | uss\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download content from a USS file to a local file on your PC.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download uss-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n ussFileName\\\\t\\\\t (string)\\\\n\\\\n The name of the USS file you want to download\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --file | -f (string)\\\\n\\\\n The path to the local file where you want to download the content. When you omit\\\\n the option, the command generates a file name automatically for you.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download the file \\\\\\"/a/ibmuser/my_text.txt\\\\\\" to\\\\n ./my_text.txt:\\\\n\\\\n $ zowe zos-files download uss-file \\\\\\"/a/ibmuser/my_text.txt\\\\\\" -f ./my_text.txt\\\\n\\\\n - Download the file \\\\\\"/a/ibmuser/MyJava.class\\\\\\" to\\\\n \\\\\\"java/MyJava.class\\\\\\" in binary mode:\\\\n\\\\n $ zowe zos-files download uss-file \\\\\\"/a/ibmuser/MyJava.class\\\\\\" -b -f \\\\\\"java/MyJava.class\\\\\\"\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-file | uf | uss\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download content from a USS file to a local file on your PC\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download uss-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n ussFileName\\\\t\\\\t (string)\\\\n\\\\n The name of the USS file you want to download\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --file | -f (string)\\\\n\\\\n The path to the local file where you want to download the content. When you omit\\\\n the option, the command generates a file name automatically for you.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download the file \\\\\\"/a/ibmuser/my_text.txt\\\\\\" to\\\\n ./my_text.txt:\\\\n\\\\n $ zowe zos-files download uss-file \\\\\\"/a/ibmuser/my_text.txt\\\\\\" -f ./my_text.txt\\\\n\\\\n - Download the file \\\\\\"/a/ibmuser/MyJava.class\\\\\\" to\\\\n \\\\\\"java/MyJava.class\\\\\\" in binary mode:\\\\n\\\\n $ zowe zos-files download uss-file \\\\\\"/a/ibmuser/MyJava.class\\\\\\" -b -f \\\\\\"java/MyJava.class\\\\\\"\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-file | uf | uss\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download content from a USS file to a local file on your PC.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download uss-file [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n ussFileName\\\\t\\\\t (string)\\\\n\\\\n The name of the USS file you want to download\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --file | -f (string)\\\\n\\\\n The path to the local file where you want to download the content. When you omit\\\\n the option, the command generates a file name automatically for you.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download the file \\\\\\"/a/ibmuser/my_text.txt\\\\\\" to\\\\n ./my_text.txt:\\\\n\\\\n $ zowe zos-files download uss-file \\\\\\"/a/ibmuser/my_text.txt\\\\\\" -f ./my_text.txt\\\\n\\\\n - Download the file \\\\\\"/a/ibmuser/MyJava.class\\\\\\" to\\\\n \\\\\\"java/MyJava.class\\\\\\" in binary mode:\\\\n\\\\n $ zowe zos-files download uss-file \\\\\\"/a/ibmuser/MyJava.class\\\\\\" -b -f \\\\\\"java/MyJava.class\\\\\\"\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/download/ussdir/__snapshots__/cli.files.download.ussdir.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/download/ussdir/__snapshots__/cli.files.download.ussdir.integration.test.ts.snap index dbe368a994..95648592c7 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/download/ussdir/__snapshots__/cli.files.download.ussdir.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/download/ussdir/__snapshots__/cli.files.download.ussdir.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Download USS Directory should display the help 1`] = ` DESCRIPTION ----------- - Download content from a USS directory to a local directory on your PC + Download content from a USS directory to a local directory on your PC. USAGE ----- @@ -30,7 +30,7 @@ exports[`Download USS Directory should display the help 1`] = ` --attributes | --attrs (local file path) - Path of an attributes file to control how files are downloaded + Path of an attributes file to control how files are downloaded. --binary | -b (boolean) @@ -70,7 +70,7 @@ exports[`Download USS Directory should display the help 1`] = ` --include-hidden | --ih (boolean) - Include hidden files and folders that have names beginning with a dot + Include hidden files and folders that have names beginning with a dot. --max-concurrent-requests | --mcr (number) @@ -102,7 +102,7 @@ exports[`Download USS Directory should display the help 1`] = ` --overwrite | --ow (boolean) - Overwrite files that already exist in your local environment + Overwrite files that already exist in your local environment. --owner (string) @@ -247,8 +247,8 @@ exports[`Download USS Directory should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: uss-directory.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-directory | uss-dir\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download content from a USS directory to a local directory on your PC\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download uss-directory [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n ussDirName\\\\t\\\\t (string)\\\\n\\\\n The name of the USS directory you want to download\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | --attrs (local file path)\\\\n\\\\n Path of an attributes file to control how files are downloaded\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --depth (number)\\\\n\\\\n Filters content in USS based on the number of directories to traverse down.\\\\n\\\\n --directory | -d (string)\\\\n\\\\n The directory to where you want to save the files. The command creates the\\\\n directory for you when it does not already exist. By default, the command\\\\n downloads the files to the current directory.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --fail-fast | --ff (boolean)\\\\n\\\\n Set this option to false to continue downloading USS files if one or more fail.\\\\n\\\\n Default value: true\\\\n\\\\n --filesys (boolean)\\\\n\\\\n Filters content in USS based on the filesystem the data is on. true - all\\\\n filesystems, false - same filesystem as search directory.\\\\n\\\\n --group (string)\\\\n\\\\n Filters content in USS based on the owning group name or ID.\\\\n\\\\n --include-hidden | --ih (boolean)\\\\n\\\\n Include hidden files and folders that have names beginning with a dot\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to download\\\\n files. Increasing the value results in faster downloads. However, increasing the\\\\n value increases resource consumption on z/OS and can be prone to errors caused\\\\n by making too many concurrent requests. If the download process encounters an\\\\n error, the following message displays:\\\\n The maximum number of TSO address spaces have been created. When you specify 0,\\\\n Zowe CLI attempts to download all files at once without a maximum number of\\\\n concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --max-length | --max (number)\\\\n\\\\n The option --max-length specifies the maximum number of items to return. Skip\\\\n this parameter to return all items. If you specify an incorrect value, the\\\\n parameter returns up to 1000 items.\\\\n\\\\n --mtime (string)\\\\n\\\\n Filters content in USS based on the last modification time. N - specify an exact\\\\n number of days, +N - older than N days, -N - newer than N days\\\\n\\\\n --name (string)\\\\n\\\\n Filters files in USS based on the name of the file or directory.\\\\n\\\\n --overwrite | --ow (boolean)\\\\n\\\\n Overwrite files that already exist in your local environment\\\\n\\\\n --owner (string)\\\\n\\\\n Filters content in USS based on the owning user name or ID.\\\\n\\\\n --perm (string)\\\\n\\\\n Filters content in USS based on the octal permissions string.\\\\n\\\\n --size (string)\\\\n\\\\n Filters content in USS based on the size. Default units are bytes. Add a suffix\\\\n of K for kilobytes, M for megabytes, or G for gigabytes. N - specify an exact\\\\n file size, +N - larger than N size, -N - smaller than N size\\\\n\\\\n --symlinks (boolean)\\\\n\\\\n Filters content in USS based on whether or not to follow symbolic links. true -\\\\n report symlinks, false - follow symlinks\\\\n\\\\n --type (string)\\\\n\\\\n Filters content in USS based on the type of content. f - regular file, d -\\\\n directory, l - symbolic link, p - FIFO named pipe, s - socket\\\\n\\\\n Allowed values: f, d, l, p, s\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download the directory \\\\\\"/a/ibmuser\\\\\\" to \\\\\\"./\\\\\\" in binary mode:\\\\n\\\\n $ zowe zos-files download uss-directory /a/ibmuser --binary\\\\n\\\\n - Download the directory \\\\\\"/a/ibmuser\\\\\\" to \\\\\\"./localDir\\\\\\":\\\\n\\\\n $ zowe zos-files download uss-directory /a/ibmuser --directory localDir\\\\n\\\\n - Download files from the directory \\\\\\"/a/ibmuser\\\\\\" that match\\\\n the name \\\\\\"*.log\\\\\\" and were modified within the last day:\\\\n\\\\n $ zowe zos-files download uss-directory /a/ibmuser --name \\\\\\"*.log\\\\\\" --mtime -1\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-directory | uss-dir\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download content from a USS directory to a local directory on your PC.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download uss-directory [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n ussDirName\\\\t\\\\t (string)\\\\n\\\\n The name of the USS directory you want to download\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | --attrs (local file path)\\\\n\\\\n Path of an attributes file to control how files are downloaded.\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --depth (number)\\\\n\\\\n Filters content in USS based on the number of directories to traverse down.\\\\n\\\\n --directory | -d (string)\\\\n\\\\n The directory to where you want to save the files. The command creates the\\\\n directory for you when it does not already exist. By default, the command\\\\n downloads the files to the current directory.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --fail-fast | --ff (boolean)\\\\n\\\\n Set this option to false to continue downloading USS files if one or more fail.\\\\n\\\\n Default value: true\\\\n\\\\n --filesys (boolean)\\\\n\\\\n Filters content in USS based on the filesystem the data is on. true - all\\\\n filesystems, false - same filesystem as search directory.\\\\n\\\\n --group (string)\\\\n\\\\n Filters content in USS based on the owning group name or ID.\\\\n\\\\n --include-hidden | --ih (boolean)\\\\n\\\\n Include hidden files and folders that have names beginning with a dot.\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to download\\\\n files. Increasing the value results in faster downloads. However, increasing the\\\\n value increases resource consumption on z/OS and can be prone to errors caused\\\\n by making too many concurrent requests. If the download process encounters an\\\\n error, the following message displays:\\\\n The maximum number of TSO address spaces have been created. When you specify 0,\\\\n Zowe CLI attempts to download all files at once without a maximum number of\\\\n concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --max-length | --max (number)\\\\n\\\\n The option --max-length specifies the maximum number of items to return. Skip\\\\n this parameter to return all items. If you specify an incorrect value, the\\\\n parameter returns up to 1000 items.\\\\n\\\\n --mtime (string)\\\\n\\\\n Filters content in USS based on the last modification time. N - specify an exact\\\\n number of days, +N - older than N days, -N - newer than N days\\\\n\\\\n --name (string)\\\\n\\\\n Filters files in USS based on the name of the file or directory.\\\\n\\\\n --overwrite | --ow (boolean)\\\\n\\\\n Overwrite files that already exist in your local environment.\\\\n\\\\n --owner (string)\\\\n\\\\n Filters content in USS based on the owning user name or ID.\\\\n\\\\n --perm (string)\\\\n\\\\n Filters content in USS based on the octal permissions string.\\\\n\\\\n --size (string)\\\\n\\\\n Filters content in USS based on the size. Default units are bytes. Add a suffix\\\\n of K for kilobytes, M for megabytes, or G for gigabytes. N - specify an exact\\\\n file size, +N - larger than N size, -N - smaller than N size\\\\n\\\\n --symlinks (boolean)\\\\n\\\\n Filters content in USS based on whether or not to follow symbolic links. true -\\\\n report symlinks, false - follow symlinks\\\\n\\\\n --type (string)\\\\n\\\\n Filters content in USS based on the type of content. f - regular file, d -\\\\n directory, l - symbolic link, p - FIFO named pipe, s - socket\\\\n\\\\n Allowed values: f, d, l, p, s\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download the directory \\\\\\"/a/ibmuser\\\\\\" to \\\\\\"./\\\\\\" in binary mode:\\\\n\\\\n $ zowe zos-files download uss-directory /a/ibmuser --binary\\\\n\\\\n - Download the directory \\\\\\"/a/ibmuser\\\\\\" to \\\\\\"./localDir\\\\\\":\\\\n\\\\n $ zowe zos-files download uss-directory /a/ibmuser --directory localDir\\\\n\\\\n - Download files from the directory \\\\\\"/a/ibmuser\\\\\\" that match\\\\n the name \\\\\\"*.log\\\\\\" and were modified within the last day:\\\\n\\\\n $ zowe zos-files download uss-directory /a/ibmuser --name \\\\\\"*.log\\\\\\" --mtime -1\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-directory | uss-dir\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download content from a USS directory to a local directory on your PC\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download uss-directory [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n ussDirName\\\\t\\\\t (string)\\\\n\\\\n The name of the USS directory you want to download\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | --attrs (local file path)\\\\n\\\\n Path of an attributes file to control how files are downloaded\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --depth (number)\\\\n\\\\n Filters content in USS based on the number of directories to traverse down.\\\\n\\\\n --directory | -d (string)\\\\n\\\\n The directory to where you want to save the files. The command creates the\\\\n directory for you when it does not already exist. By default, the command\\\\n downloads the files to the current directory.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --fail-fast | --ff (boolean)\\\\n\\\\n Set this option to false to continue downloading USS files if one or more fail.\\\\n\\\\n Default value: true\\\\n\\\\n --filesys (boolean)\\\\n\\\\n Filters content in USS based on the filesystem the data is on. true - all\\\\n filesystems, false - same filesystem as search directory.\\\\n\\\\n --group (string)\\\\n\\\\n Filters content in USS based on the owning group name or ID.\\\\n\\\\n --include-hidden | --ih (boolean)\\\\n\\\\n Include hidden files and folders that have names beginning with a dot\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to download\\\\n files. Increasing the value results in faster downloads. However, increasing the\\\\n value increases resource consumption on z/OS and can be prone to errors caused\\\\n by making too many concurrent requests. If the download process encounters an\\\\n error, the following message displays:\\\\n The maximum number of TSO address spaces have been created. When you specify 0,\\\\n Zowe CLI attempts to download all files at once without a maximum number of\\\\n concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --max-length | --max (number)\\\\n\\\\n The option --max-length specifies the maximum number of items to return. Skip\\\\n this parameter to return all items. If you specify an incorrect value, the\\\\n parameter returns up to 1000 items.\\\\n\\\\n --mtime (string)\\\\n\\\\n Filters content in USS based on the last modification time. N - specify an exact\\\\n number of days, +N - older than N days, -N - newer than N days\\\\n\\\\n --name (string)\\\\n\\\\n Filters files in USS based on the name of the file or directory.\\\\n\\\\n --overwrite | --ow (boolean)\\\\n\\\\n Overwrite files that already exist in your local environment\\\\n\\\\n --owner (string)\\\\n\\\\n Filters content in USS based on the owning user name or ID.\\\\n\\\\n --perm (string)\\\\n\\\\n Filters content in USS based on the octal permissions string.\\\\n\\\\n --size (string)\\\\n\\\\n Filters content in USS based on the size. Default units are bytes. Add a suffix\\\\n of K for kilobytes, M for megabytes, or G for gigabytes. N - specify an exact\\\\n file size, +N - larger than N size, -N - smaller than N size\\\\n\\\\n --symlinks (boolean)\\\\n\\\\n Filters content in USS based on whether or not to follow symbolic links. true -\\\\n report symlinks, false - follow symlinks\\\\n\\\\n --type (string)\\\\n\\\\n Filters content in USS based on the type of content. f - regular file, d -\\\\n directory, l - symbolic link, p - FIFO named pipe, s - socket\\\\n\\\\n Allowed values: f, d, l, p, s\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download the directory \\\\\\"/a/ibmuser\\\\\\" to \\\\\\"./\\\\\\" in binary mode:\\\\n\\\\n $ zowe zos-files download uss-directory /a/ibmuser --binary\\\\n\\\\n - Download the directory \\\\\\"/a/ibmuser\\\\\\" to \\\\\\"./localDir\\\\\\":\\\\n\\\\n $ zowe zos-files download uss-directory /a/ibmuser --directory localDir\\\\n\\\\n - Download files from the directory \\\\\\"/a/ibmuser\\\\\\" that match\\\\n the name \\\\\\"*.log\\\\\\" and were modified within the last day:\\\\n\\\\n $ zowe zos-files download uss-directory /a/ibmuser --name \\\\\\"*.log\\\\\\" --mtime -1\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-directory | uss-dir\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Download content from a USS directory to a local directory on your PC.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files download uss-directory [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n ussDirName\\\\t\\\\t (string)\\\\n\\\\n The name of the USS directory you want to download\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | --attrs (local file path)\\\\n\\\\n Path of an attributes file to control how files are downloaded.\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Download the file content in binary mode, which means that no data conversion is\\\\n performed. The data transfer process returns each line as-is, without\\\\n translation. No delimiters are added between records.\\\\n\\\\n --depth (number)\\\\n\\\\n Filters content in USS based on the number of directories to traverse down.\\\\n\\\\n --directory | -d (string)\\\\n\\\\n The directory to where you want to save the files. The command creates the\\\\n directory for you when it does not already exist. By default, the command\\\\n downloads the files to the current directory.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Download the file content with encoding mode, which means that data conversion\\\\n is performed using the file encoding specified.\\\\n\\\\n --fail-fast | --ff (boolean)\\\\n\\\\n Set this option to false to continue downloading USS files if one or more fail.\\\\n\\\\n Default value: true\\\\n\\\\n --filesys (boolean)\\\\n\\\\n Filters content in USS based on the filesystem the data is on. true - all\\\\n filesystems, false - same filesystem as search directory.\\\\n\\\\n --group (string)\\\\n\\\\n Filters content in USS based on the owning group name or ID.\\\\n\\\\n --include-hidden | --ih (boolean)\\\\n\\\\n Include hidden files and folders that have names beginning with a dot.\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to download\\\\n files. Increasing the value results in faster downloads. However, increasing the\\\\n value increases resource consumption on z/OS and can be prone to errors caused\\\\n by making too many concurrent requests. If the download process encounters an\\\\n error, the following message displays:\\\\n The maximum number of TSO address spaces have been created. When you specify 0,\\\\n Zowe CLI attempts to download all files at once without a maximum number of\\\\n concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --max-length | --max (number)\\\\n\\\\n The option --max-length specifies the maximum number of items to return. Skip\\\\n this parameter to return all items. If you specify an incorrect value, the\\\\n parameter returns up to 1000 items.\\\\n\\\\n --mtime (string)\\\\n\\\\n Filters content in USS based on the last modification time. N - specify an exact\\\\n number of days, +N - older than N days, -N - newer than N days\\\\n\\\\n --name (string)\\\\n\\\\n Filters files in USS based on the name of the file or directory.\\\\n\\\\n --overwrite | --ow (boolean)\\\\n\\\\n Overwrite files that already exist in your local environment.\\\\n\\\\n --owner (string)\\\\n\\\\n Filters content in USS based on the owning user name or ID.\\\\n\\\\n --perm (string)\\\\n\\\\n Filters content in USS based on the octal permissions string.\\\\n\\\\n --size (string)\\\\n\\\\n Filters content in USS based on the size. Default units are bytes. Add a suffix\\\\n of K for kilobytes, M for megabytes, or G for gigabytes. N - specify an exact\\\\n file size, +N - larger than N size, -N - smaller than N size\\\\n\\\\n --symlinks (boolean)\\\\n\\\\n Filters content in USS based on whether or not to follow symbolic links. true -\\\\n report symlinks, false - follow symlinks\\\\n\\\\n --type (string)\\\\n\\\\n Filters content in USS based on the type of content. f - regular file, d -\\\\n directory, l - symbolic link, p - FIFO named pipe, s - socket\\\\n\\\\n Allowed values: f, d, l, p, s\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Download the directory \\\\\\"/a/ibmuser\\\\\\" to \\\\\\"./\\\\\\" in binary mode:\\\\n\\\\n $ zowe zos-files download uss-directory /a/ibmuser --binary\\\\n\\\\n - Download the directory \\\\\\"/a/ibmuser\\\\\\" to \\\\\\"./localDir\\\\\\":\\\\n\\\\n $ zowe zos-files download uss-directory /a/ibmuser --directory localDir\\\\n\\\\n - Download files from the directory \\\\\\"/a/ibmuser\\\\\\" that match\\\\n the name \\\\\\"*.log\\\\\\" and were modified within the last day:\\\\n\\\\n $ zowe zos-files download uss-directory /a/ibmuser --name \\\\\\"*.log\\\\\\" --mtime -1\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/edit/uss/__snapshots__/edit.uss.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/edit/uss/__snapshots__/edit.uss.integration.test.ts.snap index 7ea83480bf..dc2221f09e 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/edit/uss/__snapshots__/edit.uss.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/edit/uss/__snapshots__/edit.uss.integration.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`View USS file should display the help 1`] = ` +exports[`Edit USS file should display the help 1`] = ` "================Z/OS FILES EDIT USS FILE HELP=============== COMMAND NAME @@ -161,7 +161,7 @@ exports[`View USS file should display the help 1`] = ` " `; -exports[`View USS file should display the help in json format 1`] = ` +exports[`Edit USS file should display the help in json format 1`] = ` "================Z/OS FILES EDIT USS FILE HELP=============== { \\"success\\": true, diff --git a/packages/cli/__tests__/zosfiles/__integration__/edit/uss/edit.uss.integration.test.ts b/packages/cli/__tests__/zosfiles/__integration__/edit/uss/edit.uss.integration.test.ts index c6cd6cfc2b..af4ba5d002 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/edit/uss/edit.uss.integration.test.ts +++ b/packages/cli/__tests__/zosfiles/__integration__/edit/uss/edit.uss.integration.test.ts @@ -16,7 +16,7 @@ import { ITestPropertiesSchema } from "../../../../../../../__tests__/__src__/pr let TEST_ENVIRONMENT: ITestEnvironment; -describe("View USS file", () => { +describe("Edit USS file", () => { beforeAll(async () => { TEST_ENVIRONMENT = await TestEnvironment.setUp({ diff --git a/packages/cli/__tests__/zosfiles/__integration__/list/ds/__snapshots__/cli.files.list.ds.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/list/ds/__snapshots__/cli.files.list.ds.integration.test.ts.snap index dbf752a489..dc36ec64e2 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/list/ds/__snapshots__/cli.files.list.ds.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/list/ds/__snapshots__/cli.files.list.ds.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`List data set should display the help 1`] = ` DESCRIPTION ----------- - List data sets that match a pattern in the data set name + List data sets that match a pattern in the data set name. USAGE ----- @@ -176,8 +176,8 @@ exports[`List data set should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: data-set.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n List data sets that match a pattern in the data set name\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files list data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name or pattern of the data set that you want to list\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Display more information about each member. Data sets with an undefined record\\\\n format display information related to executable modules. Variable and fixed\\\\n block data sets display information about when the members were created and\\\\n modified.\\\\n\\\\n --max-length | --max (number)\\\\n\\\\n The option --max-length specifies the maximum number of items to return. Skip\\\\n this parameter to return all items. If you specify an incorrect value, the\\\\n parameter returns up to 1000 items.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --start | -s (string)\\\\n\\\\n An optional search parameter that specifies the first data set name to return in\\\\n the response document.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Show the data set \\\\\\"ibmuser.asm\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.asm\\\\\\"\\\\n\\\\n - Show attributes of the data set \\\\\\"ibmuser.cntl\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.cntl\\\\\\" -a\\\\n\\\\n - Show all data sets of the user \\\\\\"ibmuser\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.*\\\\\\"\\\\n\\\\n - Show attributes of all data sets of the user \\\\\\"ibmuser\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.*\\\\\\" -a\\\\n\\\\n - Show the first 5 data sets of the user \\\\\\"ibmuser\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.cntl\\\\\\" --max 5\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n List data sets that match a pattern in the data set name.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files list data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name or pattern of the data set that you want to list\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Display more information about each member. Data sets with an undefined record\\\\n format display information related to executable modules. Variable and fixed\\\\n block data sets display information about when the members were created and\\\\n modified.\\\\n\\\\n --max-length | --max (number)\\\\n\\\\n The option --max-length specifies the maximum number of items to return. Skip\\\\n this parameter to return all items. If you specify an incorrect value, the\\\\n parameter returns up to 1000 items.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --start | -s (string)\\\\n\\\\n An optional search parameter that specifies the first data set name to return in\\\\n the response document.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Show the data set \\\\\\"ibmuser.asm\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.asm\\\\\\"\\\\n\\\\n - Show attributes of the data set \\\\\\"ibmuser.cntl\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.cntl\\\\\\" -a\\\\n\\\\n - Show all data sets of the user \\\\\\"ibmuser\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.*\\\\\\"\\\\n\\\\n - Show attributes of all data sets of the user \\\\\\"ibmuser\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.*\\\\\\" -a\\\\n\\\\n - Show the first 5 data sets of the user \\\\\\"ibmuser\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.cntl\\\\\\" --max 5\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n List data sets that match a pattern in the data set name\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files list data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name or pattern of the data set that you want to list\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Display more information about each member. Data sets with an undefined record\\\\n format display information related to executable modules. Variable and fixed\\\\n block data sets display information about when the members were created and\\\\n modified.\\\\n\\\\n --max-length | --max (number)\\\\n\\\\n The option --max-length specifies the maximum number of items to return. Skip\\\\n this parameter to return all items. If you specify an incorrect value, the\\\\n parameter returns up to 1000 items.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --start | -s (string)\\\\n\\\\n An optional search parameter that specifies the first data set name to return in\\\\n the response document.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Show the data set \\\\\\"ibmuser.asm\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.asm\\\\\\"\\\\n\\\\n - Show attributes of the data set \\\\\\"ibmuser.cntl\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.cntl\\\\\\" -a\\\\n\\\\n - Show all data sets of the user \\\\\\"ibmuser\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.*\\\\\\"\\\\n\\\\n - Show attributes of all data sets of the user \\\\\\"ibmuser\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.*\\\\\\" -a\\\\n\\\\n - Show the first 5 data sets of the user \\\\\\"ibmuser\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.cntl\\\\\\" --max 5\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n List data sets that match a pattern in the data set name.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files list data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name or pattern of the data set that you want to list\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --attributes | -a (boolean)\\\\n\\\\n Display more information about each member. Data sets with an undefined record\\\\n format display information related to executable modules. Variable and fixed\\\\n block data sets display information about when the members were created and\\\\n modified.\\\\n\\\\n --max-length | --max (number)\\\\n\\\\n The option --max-length specifies the maximum number of items to return. Skip\\\\n this parameter to return all items. If you specify an incorrect value, the\\\\n parameter returns up to 1000 items.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --start | -s (string)\\\\n\\\\n An optional search parameter that specifies the first data set name to return in\\\\n the response document.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Show the data set \\\\\\"ibmuser.asm\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.asm\\\\\\"\\\\n\\\\n - Show attributes of the data set \\\\\\"ibmuser.cntl\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.cntl\\\\\\" -a\\\\n\\\\n - Show all data sets of the user \\\\\\"ibmuser\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.*\\\\\\"\\\\n\\\\n - Show attributes of all data sets of the user \\\\\\"ibmuser\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.*\\\\\\" -a\\\\n\\\\n - Show the first 5 data sets of the user \\\\\\"ibmuser\\\\\\":\\\\n\\\\n $ zowe zos-files list data-set \\\\\\"ibmuser.cntl\\\\\\" --max 5\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/list/uss/__snapshots__/cli.files.list.uss.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/list/uss/__snapshots__/cli.files.list.uss.integration.test.ts.snap index 2fe3d8a801..5813ff7de4 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/list/uss/__snapshots__/cli.files.list.uss.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/list/uss/__snapshots__/cli.files.list.uss.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`List USS file should display the help 1`] = ` DESCRIPTION ----------- - List USS files and directories in a UNIX file path + List USS files and directories in a UNIX file path. USAGE ----- @@ -188,8 +188,8 @@ exports[`List USS file should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: uss-files.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-files | uf | uss\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n List USS files and directories in a UNIX file path\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files list uss-files [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n path\\\\t\\\\t (string)\\\\n\\\\n The directory containing the files and directories to be listed\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --max-length | --max (number)\\\\n\\\\n The option --max-length specifies the maximum number of items to return. Skip\\\\n this parameter to return all items. If you specify an incorrect value, the\\\\n parameter returns up to 1000 items.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Show the files and directories in path '/u/ibmuser':\\\\n\\\\n $ zowe zos-files list uss-files \\\\\\"/u/ibmuser\\\\\\"\\\\n\\\\n - Show the files and directories in path '/u/ibmuser\\\\n displaying only the file or directory name:\\\\n\\\\n $ zowe zos-files list uss-files \\\\\\"/u/ibmuser\\\\\\" --rff name\\\\n\\\\n - Show the files and directories in path '/u/ibmuser'\\\\n displaying the headers associated with the file detail:\\\\n\\\\n $ zowe zos-files list uss-files \\\\\\"/u/ibmuser\\\\\\" --rfh\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-files | uf | uss\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n List USS files and directories in a UNIX file path.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files list uss-files [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n path\\\\t\\\\t (string)\\\\n\\\\n The directory containing the files and directories to be listed\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --max-length | --max (number)\\\\n\\\\n The option --max-length specifies the maximum number of items to return. Skip\\\\n this parameter to return all items. If you specify an incorrect value, the\\\\n parameter returns up to 1000 items.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Show the files and directories in path '/u/ibmuser':\\\\n\\\\n $ zowe zos-files list uss-files \\\\\\"/u/ibmuser\\\\\\"\\\\n\\\\n - Show the files and directories in path '/u/ibmuser\\\\n displaying only the file or directory name:\\\\n\\\\n $ zowe zos-files list uss-files \\\\\\"/u/ibmuser\\\\\\" --rff name\\\\n\\\\n - Show the files and directories in path '/u/ibmuser'\\\\n displaying the headers associated with the file detail:\\\\n\\\\n $ zowe zos-files list uss-files \\\\\\"/u/ibmuser\\\\\\" --rfh\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-files | uf | uss\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n List USS files and directories in a UNIX file path\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files list uss-files [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n path\\\\t\\\\t (string)\\\\n\\\\n The directory containing the files and directories to be listed\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --max-length | --max (number)\\\\n\\\\n The option --max-length specifies the maximum number of items to return. Skip\\\\n this parameter to return all items. If you specify an incorrect value, the\\\\n parameter returns up to 1000 items.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Show the files and directories in path '/u/ibmuser':\\\\n\\\\n $ zowe zos-files list uss-files \\\\\\"/u/ibmuser\\\\\\"\\\\n\\\\n - Show the files and directories in path '/u/ibmuser\\\\n displaying only the file or directory name:\\\\n\\\\n $ zowe zos-files list uss-files \\\\\\"/u/ibmuser\\\\\\" --rff name\\\\n\\\\n - Show the files and directories in path '/u/ibmuser'\\\\n displaying the headers associated with the file detail:\\\\n\\\\n $ zowe zos-files list uss-files \\\\\\"/u/ibmuser\\\\\\" --rfh\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n uss-files | uf | uss\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n List USS files and directories in a UNIX file path.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files list uss-files [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n path\\\\t\\\\t (string)\\\\n\\\\n The directory containing the files and directories to be listed\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --max-length | --max (number)\\\\n\\\\n The option --max-length specifies the maximum number of items to return. Skip\\\\n this parameter to return all items. If you specify an incorrect value, the\\\\n parameter returns up to 1000 items.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n RESPONSE FORMAT OPTIONS\\\\n -----------------------\\\\n\\\\n --response-format-filter | --rff (array)\\\\n\\\\n Filter (include) fields in the response. Accepts an array of field/property\\\\n names to include in the output response. You can filter JSON objects properties\\\\n OR table columns/fields. In addition, you can use this option in conjunction\\\\n with '--response-format-type' to reduce the output of a command to a single\\\\n field/property or a list of a single field/property.\\\\n\\\\n --response-format-type | --rft (string)\\\\n\\\\n The command response output format type. Must be one of the following:\\\\n\\\\n table: Formats output data as a table. Use this option when the output data is\\\\n an array of homogeneous JSON objects. Each property of the object will become a\\\\n column in the table.\\\\n\\\\n list: Formats output data as a list of strings. Can be used on any data type\\\\n (JSON objects/arrays) are stringified and a new line is added after each entry\\\\n in an array.\\\\n\\\\n object: Formats output data as a list of prettified objects (or single object).\\\\n Can be used in place of \\\\\\"table\\\\\\" to change from tabular output to a list of\\\\n prettified objects.\\\\n\\\\n string: Formats output data as a string. JSON objects/arrays are stringified.\\\\n\\\\n Allowed values: table, list, object, string\\\\n\\\\n --response-format-header | --rfh (boolean)\\\\n\\\\n If \\\\\\"--response-format-type table\\\\\\" is specified, include the column headers in\\\\n the output.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Show the files and directories in path '/u/ibmuser':\\\\n\\\\n $ zowe zos-files list uss-files \\\\\\"/u/ibmuser\\\\\\"\\\\n\\\\n - Show the files and directories in path '/u/ibmuser\\\\n displaying only the file or directory name:\\\\n\\\\n $ zowe zos-files list uss-files \\\\\\"/u/ibmuser\\\\\\" --rff name\\\\n\\\\n - Show the files and directories in path '/u/ibmuser'\\\\n displaying the headers associated with the file detail:\\\\n\\\\n $ zowe zos-files list uss-files \\\\\\"/u/ibmuser\\\\\\" --rfh\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/search/ds/__scripts__/command/command_search_data_sets.sh b/packages/cli/__tests__/zosfiles/__integration__/search/ds/__scripts__/command/command_search_data_sets.sh new file mode 100755 index 0000000000..4ccccd5b9e --- /dev/null +++ b/packages/cli/__tests__/zosfiles/__integration__/search/ds/__scripts__/command/command_search_data_sets.sh @@ -0,0 +1,10 @@ +#!/bin/bash +dsn=$1 +searchterm=$2 +set -e + +zowe zos-files search ds "$dsn" "$searchterm" --host fakehost --pw fakepass --user fakeuser $3 +if [ $? -gt 0 ] +then + exit $? +fi \ No newline at end of file diff --git a/packages/cli/__tests__/zosfiles/__integration__/search/ds/__scripts__/command_search_data_sets_help.sh b/packages/cli/__tests__/zosfiles/__integration__/search/ds/__scripts__/command_search_data_sets_help.sh new file mode 100755 index 0000000000..a41fb3fa3a --- /dev/null +++ b/packages/cli/__tests__/zosfiles/__integration__/search/ds/__scripts__/command_search_data_sets_help.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -e + +echo "================Z/OS FILES SEARCH DATA SETS HELP===============" +zowe zos-files search ds --help +if [ $? -gt 0 ] +then + exit $? +fi + +echo "================Z/OS FILES SEARCH DATA SETS HELP WITH RFJ===========" +zowe zos-files search ds --help --rfj +exit $? \ No newline at end of file diff --git a/packages/cli/__tests__/zosfiles/__integration__/search/ds/__snapshots__/cli.files.search.ds.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/search/ds/__snapshots__/cli.files.search.ds.integration.test.ts.snap new file mode 100644 index 0000000000..85fab12382 --- /dev/null +++ b/packages/cli/__tests__/zosfiles/__integration__/search/ds/__snapshots__/cli.files.search.ds.integration.test.ts.snap @@ -0,0 +1,201 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Search data sets should display the help 1`] = ` +"================Z/OS FILES SEARCH DATA SETS HELP=============== + + COMMAND NAME + ------------ + + data-sets | ds + + DESCRIPTION + ----------- + + Search all data sets and PDS members that match the data set name for a search + term. + + USAGE + ----- + + zowe zos-files search data-sets [options] + + POSITIONAL ARGUMENTS + -------------------- + + pattern (string) + + The pattern to match data sets against. Also known as 'DSLEVEL'. The following + special sequences can be used in the pattern: + %: matches any single character + *: matches any number of characters within a data set name qualifier (e.g. + \\"ibmuser.j*.old\\" matches \\"ibmuser.jcl.old\\" but not \\"ibmuser.jcl.very.old\\") + **: matches any number of characters within any number of data set name + qualifiers (e.g. \\"ibmuser.**.old\\" matches both \\"ibmuser.jcl.old\\" and + \\"ibmuser.jcl.very.old\\") + However, the pattern cannot begin with any of these sequences. You can specify + multiple patterns separated by commas, for example + \\"ibmuser.**.cntl,ibmuser.**.jcl\\" + + searchString (string) + + The parameter to search for + + OPTIONS + ------- + + --case-sensitive | --cs (boolean) + + The search should be case sensitive + + Default value: false + + --mainframe-search | --ms (boolean) + + Perform a preliminary search on the mainframe, reducing network traffic. + However, this option does not work with data sets that contain binary data. This + option should be omitted if any data sets may be in binary format. Failure to do + so may result in an incomplete set of search results. + + Default value: false + + --max-concurrent-requests | --mcr (number) + + Specifies the maximum number of concurrent z/OSMF REST API requests to search + files. Increasing the value results in faster searches. However, increasing the + value increases resource consumption on z/OS and can be prone to errors caused + by making too many concurrent requests. + + Default value: 1 + + --timeout | --to (number) + + The number of seconds to search before timing out + + --response-timeout | --rto (number) + + The maximum amount of time in seconds the z/OSMF Files TSO servlet should run + before returning a response. Any request exceeding this amount of time will be + terminated and return an error. Allowed values: 5 - 600 + + ZOSMF CONNECTION OPTIONS + ------------------------ + + --host | -H (string) + + The z/OSMF server host name. + + --port | -P (number) + + The z/OSMF server port. + + Default value: 443 + + --user | -u (string) + + Mainframe (z/OSMF) user name, which can be the same as your TSO login. + + --password | --pass | --pw (string) + + Mainframe (z/OSMF) password, which can be the same as your TSO password. + + --reject-unauthorized | --ru (boolean) + + Reject self-signed certificates. + + Default value: true + + --base-path | --bp (string) + + The base path for your API mediation layer instance. Specify this option to + prepend the base path to all z/OSMF resources when making REST requests. Do not + specify this option if you are not using an API mediation layer. + + --protocol (string) + + The protocol used (HTTP or HTTPS) + + Default value: https + Allowed values: http, https + + --cert-file (local file path) + + The file path to a certificate file to use for authentication + + --cert-key-file (local file path) + + The file path to a certificate key file to use for authentication + + PROFILE OPTIONS + --------------- + + --zosmf-profile | --zosmf-p (string) + + The name of a (zosmf) profile to load for this command execution. + + --base-profile | --base-p (string) + + The name of a (base) profile to load for this command execution. + + BASE CONNECTION OPTIONS + ----------------------- + + --token-type | --tt (string) + + The type of token to get and use for the API. Omit this option to use the + default token type, which is provided by 'zowe auth login'. + + --token-value | --tv (string) + + The value of the token to pass to the API. + + GLOBAL OPTIONS + -------------- + + --show-inputs-only (boolean) + + Show command inputs and do not run the command + + --response-format-json | --rfj (boolean) + + Produce JSON formatted data from a command + + --help | -h (boolean) + + Display help text + + --help-web | --hw (boolean) + + Display HTML help in browser + + EXAMPLES + -------- + + - Search all of IBMUSER's, data sets for 'ZOWE': + + $ zowe zos-files search data-sets 'IBMUSER.*' 'ZOWE' + + - Search all of IBMUSER's, data sets for 'ZOWE' in uppercase + only: + + $ zowe zos-files search data-sets 'IBMUSER.*' 'ZOWE' --case-sensitive + + - Search all of IBMUSER's, data sets for 'ZOWE', and time out + in 1 minute: + + $ zowe zos-files search data-sets 'IBMUSER.*' 'ZOWE' --timeout 60 + + - Search all of IBMUSER's, data sets for 'ZOWE', and perform + 8 parallel tasks: + + $ zowe zos-files search data-sets 'IBMUSER.*' 'ZOWE' --max-concurrent-requests 8 + +================Z/OS FILES SEARCH DATA SETS HELP WITH RFJ=========== +{ + \\"success\\": true, + \\"exitCode\\": 0, + \\"message\\": \\"The help was constructed for command: data-sets.\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-sets | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Search all data sets and PDS members that match the data set name for a search\\\\n term.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files search data-sets [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n pattern\\\\t\\\\t (string)\\\\n\\\\n The pattern to match data sets against. Also known as 'DSLEVEL'. The following\\\\n special sequences can be used in the pattern:\\\\n %: matches any single character\\\\n *: matches any number of characters within a data set name qualifier (e.g.\\\\n \\\\\\"ibmuser.j*.old\\\\\\" matches \\\\\\"ibmuser.jcl.old\\\\\\" but not \\\\\\"ibmuser.jcl.very.old\\\\\\")\\\\n **: matches any number of characters within any number of data set name\\\\n qualifiers (e.g. \\\\\\"ibmuser.**.old\\\\\\" matches both \\\\\\"ibmuser.jcl.old\\\\\\" and\\\\n \\\\\\"ibmuser.jcl.very.old\\\\\\")\\\\n However, the pattern cannot begin with any of these sequences. You can specify\\\\n multiple patterns separated by commas, for example\\\\n \\\\\\"ibmuser.**.cntl,ibmuser.**.jcl\\\\\\"\\\\n\\\\n searchString\\\\t\\\\t (string)\\\\n\\\\n The parameter to search for\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --case-sensitive | --cs (boolean)\\\\n\\\\n The search should be case sensitive\\\\n\\\\n Default value: false\\\\n\\\\n --mainframe-search | --ms (boolean)\\\\n\\\\n Perform a preliminary search on the mainframe, reducing network traffic.\\\\n However, this option does not work with data sets that contain binary data. This\\\\n option should be omitted if any data sets may be in binary format. Failure to do\\\\n so may result in an incomplete set of search results.\\\\n\\\\n Default value: false\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to search\\\\n files. Increasing the value results in faster searches. However, increasing the\\\\n value increases resource consumption on z/OS and can be prone to errors caused\\\\n by making too many concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --timeout | --to (number)\\\\n\\\\n The number of seconds to search before timing out\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Search all of IBMUSER's, data sets for 'ZOWE':\\\\n\\\\n $ zowe zos-files search data-sets 'IBMUSER.*' 'ZOWE'\\\\n\\\\n - Search all of IBMUSER's, data sets for 'ZOWE' in uppercase\\\\n only:\\\\n\\\\n $ zowe zos-files search data-sets 'IBMUSER.*' 'ZOWE' --case-sensitive\\\\n\\\\n - Search all of IBMUSER's, data sets for 'ZOWE', and time out\\\\n in 1 minute:\\\\n\\\\n $ zowe zos-files search data-sets 'IBMUSER.*' 'ZOWE' --timeout 60\\\\n\\\\n - Search all of IBMUSER's, data sets for 'ZOWE', and perform\\\\n 8 parallel tasks:\\\\n\\\\n $ zowe zos-files search data-sets 'IBMUSER.*' 'ZOWE' --max-concurrent-requests 8\\\\n\\\\n\\", + \\"stderr\\": \\"\\", + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-sets | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Search all data sets and PDS members that match the data set name for a search\\\\n term.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files search data-sets [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n pattern\\\\t\\\\t (string)\\\\n\\\\n The pattern to match data sets against. Also known as 'DSLEVEL'. The following\\\\n special sequences can be used in the pattern:\\\\n %: matches any single character\\\\n *: matches any number of characters within a data set name qualifier (e.g.\\\\n \\\\\\"ibmuser.j*.old\\\\\\" matches \\\\\\"ibmuser.jcl.old\\\\\\" but not \\\\\\"ibmuser.jcl.very.old\\\\\\")\\\\n **: matches any number of characters within any number of data set name\\\\n qualifiers (e.g. \\\\\\"ibmuser.**.old\\\\\\" matches both \\\\\\"ibmuser.jcl.old\\\\\\" and\\\\n \\\\\\"ibmuser.jcl.very.old\\\\\\")\\\\n However, the pattern cannot begin with any of these sequences. You can specify\\\\n multiple patterns separated by commas, for example\\\\n \\\\\\"ibmuser.**.cntl,ibmuser.**.jcl\\\\\\"\\\\n\\\\n searchString\\\\t\\\\t (string)\\\\n\\\\n The parameter to search for\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --case-sensitive | --cs (boolean)\\\\n\\\\n The search should be case sensitive\\\\n\\\\n Default value: false\\\\n\\\\n --mainframe-search | --ms (boolean)\\\\n\\\\n Perform a preliminary search on the mainframe, reducing network traffic.\\\\n However, this option does not work with data sets that contain binary data. This\\\\n option should be omitted if any data sets may be in binary format. Failure to do\\\\n so may result in an incomplete set of search results.\\\\n\\\\n Default value: false\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to search\\\\n files. Increasing the value results in faster searches. However, increasing the\\\\n value increases resource consumption on z/OS and can be prone to errors caused\\\\n by making too many concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --timeout | --to (number)\\\\n\\\\n The number of seconds to search before timing out\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Search all of IBMUSER's, data sets for 'ZOWE':\\\\n\\\\n $ zowe zos-files search data-sets 'IBMUSER.*' 'ZOWE'\\\\n\\\\n - Search all of IBMUSER's, data sets for 'ZOWE' in uppercase\\\\n only:\\\\n\\\\n $ zowe zos-files search data-sets 'IBMUSER.*' 'ZOWE' --case-sensitive\\\\n\\\\n - Search all of IBMUSER's, data sets for 'ZOWE', and time out\\\\n in 1 minute:\\\\n\\\\n $ zowe zos-files search data-sets 'IBMUSER.*' 'ZOWE' --timeout 60\\\\n\\\\n - Search all of IBMUSER's, data sets for 'ZOWE', and perform\\\\n 8 parallel tasks:\\\\n\\\\n $ zowe zos-files search data-sets 'IBMUSER.*' 'ZOWE' --max-concurrent-requests 8\\\\n\\\\n\\" +}" +`; diff --git a/packages/cli/__tests__/zosfiles/__integration__/search/ds/cli.files.search.ds.integration.test.ts b/packages/cli/__tests__/zosfiles/__integration__/search/ds/cli.files.search.ds.integration.test.ts new file mode 100644 index 0000000000..8872566e4d --- /dev/null +++ b/packages/cli/__tests__/zosfiles/__integration__/search/ds/cli.files.search.ds.integration.test.ts @@ -0,0 +1,76 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import * as path from "path"; +import { ITestEnvironment, runCliScript } from "@zowe/cli-test-utils"; +import { TestEnvironment } from "../../../../../../../__tests__/__src__/environment/TestEnvironment"; +import { ITestPropertiesSchema } from "../../../../../../../__tests__/__src__/properties/ITestPropertiesSchema"; + +let TEST_ENVIRONMENT: ITestEnvironment; + +describe("Search data sets", () => { + + beforeAll(async () => { + TEST_ENVIRONMENT = await TestEnvironment.setUp({ + testName: "search_data_sets_integration", + skipProperties: true + }); + }); + + afterAll(async () => { + await TestEnvironment.cleanUp(TEST_ENVIRONMENT); + }); + + it("should display the help", () => { + const shellScript = path.join(__dirname, "__scripts__", "command_search_data_sets_help.sh"); + const response = runCliScript(shellScript, TEST_ENVIRONMENT); + expect(response.status).toBe(0); + expect(response.stderr.toString()).toBe(""); + expect(response.stdout.toString()).toMatchSnapshot(); + }); + + it("should fail due to missing data set name", () => { + const shellScript = path.join(__dirname, "__scripts__", "command", "command_search_data_sets.sh"); + const response = runCliScript(shellScript, TEST_ENVIRONMENT, [""]); + expect(response.status).toBe(1); + expect(response.stderr.toString()).toContain("Missing Positional Argument"); + expect(response.stderr.toString()).toContain("pattern"); + }); + + it("should fail due to missing search parameter", () => { + const shellScript = path.join(__dirname, "__scripts__", "command", "command_search_data_sets.sh"); + const response = runCliScript(shellScript, TEST_ENVIRONMENT, ["IBMUSER.*"]); + expect(response.status).toBe(1); + expect(response.stderr.toString()).toContain("Missing Positional Argument"); + expect(response.stderr.toString()).toContain("searchString"); + }); + + it("should fail if the maximum concurrent requests are out of range 1", () => { + const shellScript = path.join(__dirname, "__scripts__", "command", "command_search_data_sets.sh"); + const response = runCliScript(shellScript, TEST_ENVIRONMENT, ["IBMUSER.*", "TESTDATA", "--max-concurrent-requests -1"]); + expect(response.status).toBe(1); + expect(response.stderr.toString()).toContain("Invalid numeric value specified for option"); + expect(response.stderr.toString()).toContain("max-concurrent-requests"); + expect(response.stderr.toString()).toContain("1 and 100"); + expect(response.stderr.toString()).toContain("-1"); + }); + + it("should fail if the maximum concurrent requests are out of range 2", () => { + const shellScript = path.join(__dirname, "__scripts__", "command", "command_search_data_sets.sh"); + const response = runCliScript(shellScript, TEST_ENVIRONMENT, ["IBMUSER.*", "TESTDATA", "--max-concurrent-requests 101"]); + expect(response.status).toBe(1); + expect(response.stderr.toString()).toContain("Invalid numeric value specified for option"); + expect(response.stderr.toString()).toContain("max-concurrent-requests"); + expect(response.stderr.toString()).toContain("1 and 100"); + expect(response.stderr.toString()).toContain("101"); + }); + +}); diff --git a/packages/cli/__tests__/zosfiles/__integration__/upload/dtp/__snapshots__/cli.files.upload.dtp.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/upload/dtp/__snapshots__/cli.files.upload.dtp.integration.test.ts.snap index 84254be4db..9336f4e8c8 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/upload/dtp/__snapshots__/cli.files.upload.dtp.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/upload/dtp/__snapshots__/cli.files.upload.dtp.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Upload directory to PDS should display the help 1`] = ` DESCRIPTION ----------- - Upload files from a local directory to a partitioned data set (PDS) + Upload files from a local directory to a partitioned data set (PDS). USAGE ----- @@ -178,8 +178,8 @@ exports[`Upload directory to PDS should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: dir-to-pds.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n dir-to-pds | dtp\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload files from a local directory to a partitioned data set (PDS)\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload dir-to-pds [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n inputdir\\\\t\\\\t (string)\\\\n\\\\n The path for a local directory that you want to upload to a PDS\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the partitioned data set to which you want to upload the files\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Data content in encoding mode, which means that data conversion is performed\\\\n according to the encoding specified.\\\\n\\\\n --migrated-recall | --mr (string)\\\\n\\\\n The method by which migrated data set is handled. By default, a migrated data\\\\n set is recalled synchronously. You can specify the following values: wait,\\\\n nowait, error\\\\n\\\\n Default value: nowait\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Data content in record mode, which means that no data conversion is performed\\\\n and the record length is prepended to the data. The data transfer process\\\\n returns each line as-is, without translation. No delimiters are added between\\\\n records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Upload a directory named \\\\\\"src\\\\\\" to a PDS named\\\\n \\\\\\"ibmuser.src\\\\\\":\\\\n\\\\n $ zowe zos-files upload dir-to-pds \\\\\\"src\\\\\\" \\\\\\"ibmuser.src\\\\\\"\\\\n\\\\n - Upload a directory named \\\\\\"src\\\\\\" to a migrated PDS named\\\\n \\\\\\"ibmuser.src\\\\\\" and wait for it to be recalled:\\\\n\\\\n $ zowe zos-files upload dir-to-pds \\\\\\"src\\\\\\" \\\\\\"ibmuser.src\\\\\\" --mr wait\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n dir-to-pds | dtp\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload files from a local directory to a partitioned data set (PDS).\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload dir-to-pds [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n inputdir\\\\t\\\\t (string)\\\\n\\\\n The path for a local directory that you want to upload to a PDS\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the partitioned data set to which you want to upload the files\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Data content in encoding mode, which means that data conversion is performed\\\\n according to the encoding specified.\\\\n\\\\n --migrated-recall | --mr (string)\\\\n\\\\n The method by which migrated data set is handled. By default, a migrated data\\\\n set is recalled synchronously. You can specify the following values: wait,\\\\n nowait, error\\\\n\\\\n Default value: nowait\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Data content in record mode, which means that no data conversion is performed\\\\n and the record length is prepended to the data. The data transfer process\\\\n returns each line as-is, without translation. No delimiters are added between\\\\n records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Upload a directory named \\\\\\"src\\\\\\" to a PDS named\\\\n \\\\\\"ibmuser.src\\\\\\":\\\\n\\\\n $ zowe zos-files upload dir-to-pds \\\\\\"src\\\\\\" \\\\\\"ibmuser.src\\\\\\"\\\\n\\\\n - Upload a directory named \\\\\\"src\\\\\\" to a migrated PDS named\\\\n \\\\\\"ibmuser.src\\\\\\" and wait for it to be recalled:\\\\n\\\\n $ zowe zos-files upload dir-to-pds \\\\\\"src\\\\\\" \\\\\\"ibmuser.src\\\\\\" --mr wait\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n dir-to-pds | dtp\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload files from a local directory to a partitioned data set (PDS)\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload dir-to-pds [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n inputdir\\\\t\\\\t (string)\\\\n\\\\n The path for a local directory that you want to upload to a PDS\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the partitioned data set to which you want to upload the files\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Data content in encoding mode, which means that data conversion is performed\\\\n according to the encoding specified.\\\\n\\\\n --migrated-recall | --mr (string)\\\\n\\\\n The method by which migrated data set is handled. By default, a migrated data\\\\n set is recalled synchronously. You can specify the following values: wait,\\\\n nowait, error\\\\n\\\\n Default value: nowait\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Data content in record mode, which means that no data conversion is performed\\\\n and the record length is prepended to the data. The data transfer process\\\\n returns each line as-is, without translation. No delimiters are added between\\\\n records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Upload a directory named \\\\\\"src\\\\\\" to a PDS named\\\\n \\\\\\"ibmuser.src\\\\\\":\\\\n\\\\n $ zowe zos-files upload dir-to-pds \\\\\\"src\\\\\\" \\\\\\"ibmuser.src\\\\\\"\\\\n\\\\n - Upload a directory named \\\\\\"src\\\\\\" to a migrated PDS named\\\\n \\\\\\"ibmuser.src\\\\\\" and wait for it to be recalled:\\\\n\\\\n $ zowe zos-files upload dir-to-pds \\\\\\"src\\\\\\" \\\\\\"ibmuser.src\\\\\\" --mr wait\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n dir-to-pds | dtp\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload files from a local directory to a partitioned data set (PDS).\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload dir-to-pds [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n inputdir\\\\t\\\\t (string)\\\\n\\\\n The path for a local directory that you want to upload to a PDS\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the partitioned data set to which you want to upload the files\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Data content in encoding mode, which means that data conversion is performed\\\\n according to the encoding specified.\\\\n\\\\n --migrated-recall | --mr (string)\\\\n\\\\n The method by which migrated data set is handled. By default, a migrated data\\\\n set is recalled synchronously. You can specify the following values: wait,\\\\n nowait, error\\\\n\\\\n Default value: nowait\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Data content in record mode, which means that no data conversion is performed\\\\n and the record length is prepended to the data. The data transfer process\\\\n returns each line as-is, without translation. No delimiters are added between\\\\n records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Upload a directory named \\\\\\"src\\\\\\" to a PDS named\\\\n \\\\\\"ibmuser.src\\\\\\":\\\\n\\\\n $ zowe zos-files upload dir-to-pds \\\\\\"src\\\\\\" \\\\\\"ibmuser.src\\\\\\"\\\\n\\\\n - Upload a directory named \\\\\\"src\\\\\\" to a migrated PDS named\\\\n \\\\\\"ibmuser.src\\\\\\" and wait for it to be recalled:\\\\n\\\\n $ zowe zos-files upload dir-to-pds \\\\\\"src\\\\\\" \\\\\\"ibmuser.src\\\\\\" --mr wait\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/upload/dtu/__snapshots__/cli.files.upload.dtu.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/upload/dtu/__snapshots__/cli.files.upload.dtu.integration.test.ts.snap index 75a3df29f6..1d9522bdb2 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/upload/dtu/__snapshots__/cli.files.upload.dtu.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/upload/dtu/__snapshots__/cli.files.upload.dtu.integration.test.ts.snap @@ -95,7 +95,7 @@ exports[`Upload local dir to uss dir should display the help 1`] = ` --attributes | --attrs (string) - Path of an attributes file to control how files are uploaded + Path of an attributes file to control how files are uploaded. --max-concurrent-requests | --mcr (number) @@ -112,7 +112,7 @@ exports[`Upload local dir to uss dir should display the help 1`] = ` --include-hidden | --ih (boolean) - Include hidden files and folders that have names beginning with a dot + Include hidden files and folders that have names beginning with a dot. --response-timeout | --rto (number) @@ -246,8 +246,8 @@ exports[`Upload local dir to uss dir should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: dir-to-uss.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n dir-to-uss | dtu\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload a local directory to a USS directory.\\\\n\\\\n An optional .zosattributes file in the source directory can be used to control\\\\n file conversion and tagging.\\\\n\\\\n An example .zosattributes file:\\\\n # pattern local-encoding remote-encoding\\\\n # Don't upload the node_modules directory\\\\n node_modules -\\\\n # Don't upload files that start with periods\\\\n .* -\\\\n # Upload jpg images in binary\\\\n *.jpg binary binary\\\\n # Convert CICS Node.js profiles to EBCDIC\\\\n *.profile ISO8859-1 EBCDIC\\\\n\\\\n Lines starting with the ‘#’ character are comments. Each line can specify up to\\\\n three positional attributes:\\\\n A pattern to match a set of files. Pattern-matching syntax follows\\\\n the same rules as those that apply in .gitignore files (note that negated\\\\n patterns that begin with ‘!’ are not supported). See\\\\n https://git-scm.com/docs/gitignore#_pattern_format.\\\\n A local-encoding to identify a file’s encoding on the local\\\\n workstation. If '-' is specified for local-encoding,files that match the pattern\\\\n are not transferred.\\\\n A remote-encoding to specify the file’s desired character set on USS.\\\\n This attribute must either match the local encoding or be set to EBCDIC. If set\\\\n to EBCDIC, files are transferred in text mode and converted, otherwise they are\\\\n transferred in binary mode. Remote files are tagged either with the remote\\\\n encoding or as binary.\\\\n\\\\n A .zosattributes file can either be placed in the top-level directory you want\\\\n to upload, or its location can be specified by using the --attributes parameter.\\\\n .zosattributes files that are placed in nested directories are ignored.\\\\n\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload dir-to-uss [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n inputDir\\\\t\\\\t (string)\\\\n\\\\n The local directory path that you want to upload to a USS directory\\\\n\\\\n USSDir\\\\t\\\\t (string)\\\\n\\\\n The name of the USS directory to which you want to upload the local directory\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --recursive | -r (boolean)\\\\n\\\\n Upload all directories recursively.\\\\n\\\\n --binary-files | --bf (string)\\\\n\\\\n Comma separated list of file names to be uploaded in binary mode. Use this\\\\n option when you upload a directory in default ASCII mode, but you want to\\\\n specify certain files to be uploaded in binary mode. All files matching\\\\n specified file names will be uploaded in binary mode. If a .zosattributes file\\\\n (or equivalent file specified via --attributes) is present, --binary-files will\\\\n be ignored.\\\\n\\\\n --ascii-files | --af (string)\\\\n\\\\n Comma separated list of file names to be uploaded in ASCII mode. Use this option\\\\n when you upload a directory with --binary/-b flag, but you want to specify\\\\n certain files to be uploaded in ASCII mode. All files matching specified file\\\\n names will be uploaded in ASCII mode. If a .zosattributes file (or equivalent\\\\n file specified via --attributes) is present, --ascii-files will be ignored.\\\\n\\\\n --attributes | --attrs (string)\\\\n\\\\n Path of an attributes file to control how files are uploaded\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to upload\\\\n files. Increasing the value results in faster uploads. However, increasing the\\\\n value increases resource consumption on z/OS and can be prone to errors caused\\\\n by making too many concurrent requests. If the upload process encounters an\\\\n error, the following message displays:\\\\n The maximum number of TSO address spaces have been created. When you specify 0,\\\\n Zowe CLI attempts to upload all members at once without a maximum number of\\\\n concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --include-hidden | --ih (boolean)\\\\n\\\\n Include hidden files and folders that have names beginning with a dot\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Upload all files from the \\\\\\"local_dir\\\\\\" directory to the\\\\n \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\"\\\\n\\\\n - Upload all files from the \\\\\\"local_dir\\\\\\" directory and all its\\\\n sub-directories, to the \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\" --recursive\\\\n\\\\n - Upload all files from the \\\\\\"local_dir\\\\\\" directory to the\\\\n \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory in default ASCII mode, while specifying a list\\\\n of file names (without path) to be uploaded in binary mode:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\" --binary-files \\\\\\"myFile1.exe,myFile2.exe,myFile3.exe\\\\\\"\\\\n\\\\n - Upload all files from the \\\\\\"local_dir\\\\\\" directory to the\\\\n \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory in binary mode, while specifying a list of\\\\n file names (without path) to be uploaded in ASCII mode:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\" --binary --ascii-files \\\\\\"myFile1.txt,myFile2.txt,myFile3.txt\\\\\\"\\\\n\\\\n - Recursively upload all files from the \\\\\\"local_dir\\\\\\" directory\\\\n to the \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory, specifying files to ignore and file\\\\n encodings in the local file my_global_attributes:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\" --recursive --attributes my_global_attributes\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n dir-to-uss | dtu\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload a local directory to a USS directory.\\\\n\\\\n An optional .zosattributes file in the source directory can be used to control\\\\n file conversion and tagging.\\\\n\\\\n An example .zosattributes file:\\\\n # pattern local-encoding remote-encoding\\\\n # Don't upload the node_modules directory\\\\n node_modules -\\\\n # Don't upload files that start with periods\\\\n .* -\\\\n # Upload jpg images in binary\\\\n *.jpg binary binary\\\\n # Convert CICS Node.js profiles to EBCDIC\\\\n *.profile ISO8859-1 EBCDIC\\\\n\\\\n Lines starting with the ‘#’ character are comments. Each line can specify up to\\\\n three positional attributes:\\\\n A pattern to match a set of files. Pattern-matching syntax follows\\\\n the same rules as those that apply in .gitignore files (note that negated\\\\n patterns that begin with ‘!’ are not supported). See\\\\n https://git-scm.com/docs/gitignore#_pattern_format.\\\\n A local-encoding to identify a file’s encoding on the local\\\\n workstation. If '-' is specified for local-encoding,files that match the pattern\\\\n are not transferred.\\\\n A remote-encoding to specify the file’s desired character set on USS.\\\\n This attribute must either match the local encoding or be set to EBCDIC. If set\\\\n to EBCDIC, files are transferred in text mode and converted, otherwise they are\\\\n transferred in binary mode. Remote files are tagged either with the remote\\\\n encoding or as binary.\\\\n\\\\n A .zosattributes file can either be placed in the top-level directory you want\\\\n to upload, or its location can be specified by using the --attributes parameter.\\\\n .zosattributes files that are placed in nested directories are ignored.\\\\n\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload dir-to-uss [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n inputDir\\\\t\\\\t (string)\\\\n\\\\n The local directory path that you want to upload to a USS directory\\\\n\\\\n USSDir\\\\t\\\\t (string)\\\\n\\\\n The name of the USS directory to which you want to upload the local directory\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --recursive | -r (boolean)\\\\n\\\\n Upload all directories recursively.\\\\n\\\\n --binary-files | --bf (string)\\\\n\\\\n Comma separated list of file names to be uploaded in binary mode. Use this\\\\n option when you upload a directory in default ASCII mode, but you want to\\\\n specify certain files to be uploaded in binary mode. All files matching\\\\n specified file names will be uploaded in binary mode. If a .zosattributes file\\\\n (or equivalent file specified via --attributes) is present, --binary-files will\\\\n be ignored.\\\\n\\\\n --ascii-files | --af (string)\\\\n\\\\n Comma separated list of file names to be uploaded in ASCII mode. Use this option\\\\n when you upload a directory with --binary/-b flag, but you want to specify\\\\n certain files to be uploaded in ASCII mode. All files matching specified file\\\\n names will be uploaded in ASCII mode. If a .zosattributes file (or equivalent\\\\n file specified via --attributes) is present, --ascii-files will be ignored.\\\\n\\\\n --attributes | --attrs (string)\\\\n\\\\n Path of an attributes file to control how files are uploaded.\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to upload\\\\n files. Increasing the value results in faster uploads. However, increasing the\\\\n value increases resource consumption on z/OS and can be prone to errors caused\\\\n by making too many concurrent requests. If the upload process encounters an\\\\n error, the following message displays:\\\\n The maximum number of TSO address spaces have been created. When you specify 0,\\\\n Zowe CLI attempts to upload all members at once without a maximum number of\\\\n concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --include-hidden | --ih (boolean)\\\\n\\\\n Include hidden files and folders that have names beginning with a dot.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Upload all files from the \\\\\\"local_dir\\\\\\" directory to the\\\\n \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\"\\\\n\\\\n - Upload all files from the \\\\\\"local_dir\\\\\\" directory and all its\\\\n sub-directories, to the \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\" --recursive\\\\n\\\\n - Upload all files from the \\\\\\"local_dir\\\\\\" directory to the\\\\n \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory in default ASCII mode, while specifying a list\\\\n of file names (without path) to be uploaded in binary mode:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\" --binary-files \\\\\\"myFile1.exe,myFile2.exe,myFile3.exe\\\\\\"\\\\n\\\\n - Upload all files from the \\\\\\"local_dir\\\\\\" directory to the\\\\n \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory in binary mode, while specifying a list of\\\\n file names (without path) to be uploaded in ASCII mode:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\" --binary --ascii-files \\\\\\"myFile1.txt,myFile2.txt,myFile3.txt\\\\\\"\\\\n\\\\n - Recursively upload all files from the \\\\\\"local_dir\\\\\\" directory\\\\n to the \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory, specifying files to ignore and file\\\\n encodings in the local file my_global_attributes:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\" --recursive --attributes my_global_attributes\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n dir-to-uss | dtu\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload a local directory to a USS directory.\\\\n\\\\n An optional .zosattributes file in the source directory can be used to control\\\\n file conversion and tagging.\\\\n\\\\n An example .zosattributes file:\\\\n # pattern local-encoding remote-encoding\\\\n # Don't upload the node_modules directory\\\\n node_modules -\\\\n # Don't upload files that start with periods\\\\n .* -\\\\n # Upload jpg images in binary\\\\n *.jpg binary binary\\\\n # Convert CICS Node.js profiles to EBCDIC\\\\n *.profile ISO8859-1 EBCDIC\\\\n\\\\n Lines starting with the ‘#’ character are comments. Each line can specify up to\\\\n three positional attributes:\\\\n A pattern to match a set of files. Pattern-matching syntax follows\\\\n the same rules as those that apply in .gitignore files (note that negated\\\\n patterns that begin with ‘!’ are not supported). See\\\\n https://git-scm.com/docs/gitignore#_pattern_format.\\\\n A local-encoding to identify a file’s encoding on the local\\\\n workstation. If '-' is specified for local-encoding,files that match the pattern\\\\n are not transferred.\\\\n A remote-encoding to specify the file’s desired character set on USS.\\\\n This attribute must either match the local encoding or be set to EBCDIC. If set\\\\n to EBCDIC, files are transferred in text mode and converted, otherwise they are\\\\n transferred in binary mode. Remote files are tagged either with the remote\\\\n encoding or as binary.\\\\n\\\\n A .zosattributes file can either be placed in the top-level directory you want\\\\n to upload, or its location can be specified by using the --attributes parameter.\\\\n .zosattributes files that are placed in nested directories are ignored.\\\\n\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload dir-to-uss [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n inputDir\\\\t\\\\t (string)\\\\n\\\\n The local directory path that you want to upload to a USS directory\\\\n\\\\n USSDir\\\\t\\\\t (string)\\\\n\\\\n The name of the USS directory to which you want to upload the local directory\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --recursive | -r (boolean)\\\\n\\\\n Upload all directories recursively.\\\\n\\\\n --binary-files | --bf (string)\\\\n\\\\n Comma separated list of file names to be uploaded in binary mode. Use this\\\\n option when you upload a directory in default ASCII mode, but you want to\\\\n specify certain files to be uploaded in binary mode. All files matching\\\\n specified file names will be uploaded in binary mode. If a .zosattributes file\\\\n (or equivalent file specified via --attributes) is present, --binary-files will\\\\n be ignored.\\\\n\\\\n --ascii-files | --af (string)\\\\n\\\\n Comma separated list of file names to be uploaded in ASCII mode. Use this option\\\\n when you upload a directory with --binary/-b flag, but you want to specify\\\\n certain files to be uploaded in ASCII mode. All files matching specified file\\\\n names will be uploaded in ASCII mode. If a .zosattributes file (or equivalent\\\\n file specified via --attributes) is present, --ascii-files will be ignored.\\\\n\\\\n --attributes | --attrs (string)\\\\n\\\\n Path of an attributes file to control how files are uploaded\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to upload\\\\n files. Increasing the value results in faster uploads. However, increasing the\\\\n value increases resource consumption on z/OS and can be prone to errors caused\\\\n by making too many concurrent requests. If the upload process encounters an\\\\n error, the following message displays:\\\\n The maximum number of TSO address spaces have been created. When you specify 0,\\\\n Zowe CLI attempts to upload all members at once without a maximum number of\\\\n concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --include-hidden | --ih (boolean)\\\\n\\\\n Include hidden files and folders that have names beginning with a dot\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Upload all files from the \\\\\\"local_dir\\\\\\" directory to the\\\\n \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\"\\\\n\\\\n - Upload all files from the \\\\\\"local_dir\\\\\\" directory and all its\\\\n sub-directories, to the \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\" --recursive\\\\n\\\\n - Upload all files from the \\\\\\"local_dir\\\\\\" directory to the\\\\n \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory in default ASCII mode, while specifying a list\\\\n of file names (without path) to be uploaded in binary mode:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\" --binary-files \\\\\\"myFile1.exe,myFile2.exe,myFile3.exe\\\\\\"\\\\n\\\\n - Upload all files from the \\\\\\"local_dir\\\\\\" directory to the\\\\n \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory in binary mode, while specifying a list of\\\\n file names (without path) to be uploaded in ASCII mode:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\" --binary --ascii-files \\\\\\"myFile1.txt,myFile2.txt,myFile3.txt\\\\\\"\\\\n\\\\n - Recursively upload all files from the \\\\\\"local_dir\\\\\\" directory\\\\n to the \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory, specifying files to ignore and file\\\\n encodings in the local file my_global_attributes:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\" --recursive --attributes my_global_attributes\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n dir-to-uss | dtu\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload a local directory to a USS directory.\\\\n\\\\n An optional .zosattributes file in the source directory can be used to control\\\\n file conversion and tagging.\\\\n\\\\n An example .zosattributes file:\\\\n # pattern local-encoding remote-encoding\\\\n # Don't upload the node_modules directory\\\\n node_modules -\\\\n # Don't upload files that start with periods\\\\n .* -\\\\n # Upload jpg images in binary\\\\n *.jpg binary binary\\\\n # Convert CICS Node.js profiles to EBCDIC\\\\n *.profile ISO8859-1 EBCDIC\\\\n\\\\n Lines starting with the ‘#’ character are comments. Each line can specify up to\\\\n three positional attributes:\\\\n A pattern to match a set of files. Pattern-matching syntax follows\\\\n the same rules as those that apply in .gitignore files (note that negated\\\\n patterns that begin with ‘!’ are not supported). See\\\\n https://git-scm.com/docs/gitignore#_pattern_format.\\\\n A local-encoding to identify a file’s encoding on the local\\\\n workstation. If '-' is specified for local-encoding,files that match the pattern\\\\n are not transferred.\\\\n A remote-encoding to specify the file’s desired character set on USS.\\\\n This attribute must either match the local encoding or be set to EBCDIC. If set\\\\n to EBCDIC, files are transferred in text mode and converted, otherwise they are\\\\n transferred in binary mode. Remote files are tagged either with the remote\\\\n encoding or as binary.\\\\n\\\\n A .zosattributes file can either be placed in the top-level directory you want\\\\n to upload, or its location can be specified by using the --attributes parameter.\\\\n .zosattributes files that are placed in nested directories are ignored.\\\\n\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload dir-to-uss [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n inputDir\\\\t\\\\t (string)\\\\n\\\\n The local directory path that you want to upload to a USS directory\\\\n\\\\n USSDir\\\\t\\\\t (string)\\\\n\\\\n The name of the USS directory to which you want to upload the local directory\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --recursive | -r (boolean)\\\\n\\\\n Upload all directories recursively.\\\\n\\\\n --binary-files | --bf (string)\\\\n\\\\n Comma separated list of file names to be uploaded in binary mode. Use this\\\\n option when you upload a directory in default ASCII mode, but you want to\\\\n specify certain files to be uploaded in binary mode. All files matching\\\\n specified file names will be uploaded in binary mode. If a .zosattributes file\\\\n (or equivalent file specified via --attributes) is present, --binary-files will\\\\n be ignored.\\\\n\\\\n --ascii-files | --af (string)\\\\n\\\\n Comma separated list of file names to be uploaded in ASCII mode. Use this option\\\\n when you upload a directory with --binary/-b flag, but you want to specify\\\\n certain files to be uploaded in ASCII mode. All files matching specified file\\\\n names will be uploaded in ASCII mode. If a .zosattributes file (or equivalent\\\\n file specified via --attributes) is present, --ascii-files will be ignored.\\\\n\\\\n --attributes | --attrs (string)\\\\n\\\\n Path of an attributes file to control how files are uploaded.\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to upload\\\\n files. Increasing the value results in faster uploads. However, increasing the\\\\n value increases resource consumption on z/OS and can be prone to errors caused\\\\n by making too many concurrent requests. If the upload process encounters an\\\\n error, the following message displays:\\\\n The maximum number of TSO address spaces have been created. When you specify 0,\\\\n Zowe CLI attempts to upload all members at once without a maximum number of\\\\n concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --include-hidden | --ih (boolean)\\\\n\\\\n Include hidden files and folders that have names beginning with a dot.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Upload all files from the \\\\\\"local_dir\\\\\\" directory to the\\\\n \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\"\\\\n\\\\n - Upload all files from the \\\\\\"local_dir\\\\\\" directory and all its\\\\n sub-directories, to the \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\" --recursive\\\\n\\\\n - Upload all files from the \\\\\\"local_dir\\\\\\" directory to the\\\\n \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory in default ASCII mode, while specifying a list\\\\n of file names (without path) to be uploaded in binary mode:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\" --binary-files \\\\\\"myFile1.exe,myFile2.exe,myFile3.exe\\\\\\"\\\\n\\\\n - Upload all files from the \\\\\\"local_dir\\\\\\" directory to the\\\\n \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory in binary mode, while specifying a list of\\\\n file names (without path) to be uploaded in ASCII mode:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\" --binary --ascii-files \\\\\\"myFile1.txt,myFile2.txt,myFile3.txt\\\\\\"\\\\n\\\\n - Recursively upload all files from the \\\\\\"local_dir\\\\\\" directory\\\\n to the \\\\\\"/a/ibmuser/my_dir\\\\\\" USS directory, specifying files to ignore and file\\\\n encodings in the local file my_global_attributes:\\\\n\\\\n $ zowe zos-files upload dir-to-uss \\\\\\"local_dir\\\\\\" \\\\\\"/a/ibmuser/my_dir\\\\\\" --recursive --attributes my_global_attributes\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/upload/ftds/__snapshots__/cli.files.upload.ftds.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/upload/ftds/__snapshots__/cli.files.upload.ftds.integration.test.ts.snap index d2d36a9346..4de3fc0536 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/upload/ftds/__snapshots__/cli.files.upload.ftds.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/upload/ftds/__snapshots__/cli.files.upload.ftds.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Upload file to data set should display the help 1`] = ` DESCRIPTION ----------- - Upload the contents of a file to a z/OS data set + Upload the contents of a file to a z/OS data set. USAGE ----- @@ -183,8 +183,8 @@ exports[`Upload file to data set should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: file-to-data-set.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n file-to-data-set | ftds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload the contents of a file to a z/OS data set\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload file-to-data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n inputfile\\\\t\\\\t (string)\\\\n\\\\n The local file that you want to upload to a data set\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set to which you want to upload the file\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Data content in encoding mode, which means that data conversion is performed\\\\n according to the encoding specified.\\\\n\\\\n --migrated-recall | --mr (string)\\\\n\\\\n The method by which migrated data set is handled. By default, a migrated data\\\\n set is recalled synchronously. You can specify the following values: wait,\\\\n nowait, error\\\\n\\\\n Default value: nowait\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Data content in record mode, which means that no data conversion is performed\\\\n and the record length is prepended to the data. The data transfer process\\\\n returns each line as-is, without translation. No delimiters are added between\\\\n records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Upload file contents to a sequential data set named\\\\n \\\\\\"ibmuser.ps\\\\\\":\\\\n\\\\n $ zowe zos-files upload file-to-data-set \\\\\\"file.txt\\\\\\" \\\\\\"ibmuser.ps\\\\\\"\\\\n\\\\n - Upload file contents to a PDS member named\\\\n \\\\\\"ibmuser.pds(mem)\\\\\\":\\\\n\\\\n $ zowe zos-files upload file-to-data-set \\\\\\"file.txt\\\\\\" \\\\\\"ibmuser.pds(mem)\\\\\\"\\\\n\\\\n - Upload file contents to a migrated data set and wait for it\\\\n to be recalled:\\\\n\\\\n $ zowe zos-files upload file-to-data-set \\\\\\"file.txt\\\\\\" \\\\\\"ibmuser.ps\\\\\\" --mr wait\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n file-to-data-set | ftds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload the contents of a file to a z/OS data set.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload file-to-data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n inputfile\\\\t\\\\t (string)\\\\n\\\\n The local file that you want to upload to a data set\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set to which you want to upload the file\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Data content in encoding mode, which means that data conversion is performed\\\\n according to the encoding specified.\\\\n\\\\n --migrated-recall | --mr (string)\\\\n\\\\n The method by which migrated data set is handled. By default, a migrated data\\\\n set is recalled synchronously. You can specify the following values: wait,\\\\n nowait, error\\\\n\\\\n Default value: nowait\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Data content in record mode, which means that no data conversion is performed\\\\n and the record length is prepended to the data. The data transfer process\\\\n returns each line as-is, without translation. No delimiters are added between\\\\n records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Upload file contents to a sequential data set named\\\\n \\\\\\"ibmuser.ps\\\\\\":\\\\n\\\\n $ zowe zos-files upload file-to-data-set \\\\\\"file.txt\\\\\\" \\\\\\"ibmuser.ps\\\\\\"\\\\n\\\\n - Upload file contents to a PDS member named\\\\n \\\\\\"ibmuser.pds(mem)\\\\\\":\\\\n\\\\n $ zowe zos-files upload file-to-data-set \\\\\\"file.txt\\\\\\" \\\\\\"ibmuser.pds(mem)\\\\\\"\\\\n\\\\n - Upload file contents to a migrated data set and wait for it\\\\n to be recalled:\\\\n\\\\n $ zowe zos-files upload file-to-data-set \\\\\\"file.txt\\\\\\" \\\\\\"ibmuser.ps\\\\\\" --mr wait\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n file-to-data-set | ftds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload the contents of a file to a z/OS data set\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload file-to-data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n inputfile\\\\t\\\\t (string)\\\\n\\\\n The local file that you want to upload to a data set\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set to which you want to upload the file\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Data content in encoding mode, which means that data conversion is performed\\\\n according to the encoding specified.\\\\n\\\\n --migrated-recall | --mr (string)\\\\n\\\\n The method by which migrated data set is handled. By default, a migrated data\\\\n set is recalled synchronously. You can specify the following values: wait,\\\\n nowait, error\\\\n\\\\n Default value: nowait\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Data content in record mode, which means that no data conversion is performed\\\\n and the record length is prepended to the data. The data transfer process\\\\n returns each line as-is, without translation. No delimiters are added between\\\\n records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Upload file contents to a sequential data set named\\\\n \\\\\\"ibmuser.ps\\\\\\":\\\\n\\\\n $ zowe zos-files upload file-to-data-set \\\\\\"file.txt\\\\\\" \\\\\\"ibmuser.ps\\\\\\"\\\\n\\\\n - Upload file contents to a PDS member named\\\\n \\\\\\"ibmuser.pds(mem)\\\\\\":\\\\n\\\\n $ zowe zos-files upload file-to-data-set \\\\\\"file.txt\\\\\\" \\\\\\"ibmuser.pds(mem)\\\\\\"\\\\n\\\\n - Upload file contents to a migrated data set and wait for it\\\\n to be recalled:\\\\n\\\\n $ zowe zos-files upload file-to-data-set \\\\\\"file.txt\\\\\\" \\\\\\"ibmuser.ps\\\\\\" --mr wait\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n file-to-data-set | ftds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload the contents of a file to a z/OS data set.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload file-to-data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n inputfile\\\\t\\\\t (string)\\\\n\\\\n The local file that you want to upload to a data set\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set to which you want to upload the file\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Data content in encoding mode, which means that data conversion is performed\\\\n according to the encoding specified.\\\\n\\\\n --migrated-recall | --mr (string)\\\\n\\\\n The method by which migrated data set is handled. By default, a migrated data\\\\n set is recalled synchronously. You can specify the following values: wait,\\\\n nowait, error\\\\n\\\\n Default value: nowait\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Data content in record mode, which means that no data conversion is performed\\\\n and the record length is prepended to the data. The data transfer process\\\\n returns each line as-is, without translation. No delimiters are added between\\\\n records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Upload file contents to a sequential data set named\\\\n \\\\\\"ibmuser.ps\\\\\\":\\\\n\\\\n $ zowe zos-files upload file-to-data-set \\\\\\"file.txt\\\\\\" \\\\\\"ibmuser.ps\\\\\\"\\\\n\\\\n - Upload file contents to a PDS member named\\\\n \\\\\\"ibmuser.pds(mem)\\\\\\":\\\\n\\\\n $ zowe zos-files upload file-to-data-set \\\\\\"file.txt\\\\\\" \\\\\\"ibmuser.pds(mem)\\\\\\"\\\\n\\\\n - Upload file contents to a migrated data set and wait for it\\\\n to be recalled:\\\\n\\\\n $ zowe zos-files upload file-to-data-set \\\\\\"file.txt\\\\\\" \\\\\\"ibmuser.ps\\\\\\" --mr wait\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/upload/ftu/__snapshots__/cli.files.upload.ftu.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/upload/ftu/__snapshots__/cli.files.upload.ftu.integration.test.ts.snap index 25f495aedb..8d37ccd150 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/upload/ftu/__snapshots__/cli.files.upload.ftu.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/upload/ftu/__snapshots__/cli.files.upload.ftu.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Upload uss file should display the help 1`] = ` DESCRIPTION ----------- - Upload content to a USS file from local file + Upload content to a USS file from local file. USAGE ----- @@ -152,8 +152,8 @@ exports[`Upload uss file should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: file-to-uss.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n file-to-uss | ftu\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload content to a USS file from local file\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload file-to-uss [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n inputfile\\\\t\\\\t (string)\\\\n\\\\n The local file that you want to upload to a USS file\\\\n\\\\n USSFileName\\\\t\\\\t (string)\\\\n\\\\n The name of the USS file to which you want to upload the file\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Data content in encoding mode, which means that data conversion is performed\\\\n according to the encoding specified.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Upload to the USS file \\\\\\"/a/ibmuser/my_text.txt\\\\\\" from the\\\\n file \\\\\\"file.txt\\\\\\":\\\\n\\\\n $ zowe zos-files upload file-to-uss \\\\\\"file.txt\\\\\\" \\\\\\"/a/ibmuser/my_text.txt\\\\\\"\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n file-to-uss | ftu\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload content to a USS file from local file.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload file-to-uss [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n inputfile\\\\t\\\\t (string)\\\\n\\\\n The local file that you want to upload to a USS file\\\\n\\\\n USSFileName\\\\t\\\\t (string)\\\\n\\\\n The name of the USS file to which you want to upload the file\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Data content in encoding mode, which means that data conversion is performed\\\\n according to the encoding specified.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Upload to the USS file \\\\\\"/a/ibmuser/my_text.txt\\\\\\" from the\\\\n file \\\\\\"file.txt\\\\\\":\\\\n\\\\n $ zowe zos-files upload file-to-uss \\\\\\"file.txt\\\\\\" \\\\\\"/a/ibmuser/my_text.txt\\\\\\"\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n file-to-uss | ftu\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload content to a USS file from local file\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload file-to-uss [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n inputfile\\\\t\\\\t (string)\\\\n\\\\n The local file that you want to upload to a USS file\\\\n\\\\n USSFileName\\\\t\\\\t (string)\\\\n\\\\n The name of the USS file to which you want to upload the file\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Data content in encoding mode, which means that data conversion is performed\\\\n according to the encoding specified.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Upload to the USS file \\\\\\"/a/ibmuser/my_text.txt\\\\\\" from the\\\\n file \\\\\\"file.txt\\\\\\":\\\\n\\\\n $ zowe zos-files upload file-to-uss \\\\\\"file.txt\\\\\\" \\\\\\"/a/ibmuser/my_text.txt\\\\\\"\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n file-to-uss | ftu\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload content to a USS file from local file.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload file-to-uss [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n inputfile\\\\t\\\\t (string)\\\\n\\\\n The local file that you want to upload to a USS file\\\\n\\\\n USSFileName\\\\t\\\\t (string)\\\\n\\\\n The name of the USS file to which you want to upload the file\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --encoding | --ec (string)\\\\n\\\\n Data content in encoding mode, which means that data conversion is performed\\\\n according to the encoding specified.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Upload to the USS file \\\\\\"/a/ibmuser/my_text.txt\\\\\\" from the\\\\n file \\\\\\"file.txt\\\\\\":\\\\n\\\\n $ zowe zos-files upload file-to-uss \\\\\\"file.txt\\\\\\" \\\\\\"/a/ibmuser/my_text.txt\\\\\\"\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__integration__/upload/stds/__snapshots__/cli.files.upload.stds.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/upload/stds/__snapshots__/cli.files.upload.stds.integration.test.ts.snap index 0b5ebd366f..9854a5978a 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/upload/stds/__snapshots__/cli.files.upload.stds.integration.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__integration__/upload/stds/__snapshots__/cli.files.upload.stds.integration.test.ts.snap @@ -11,7 +11,7 @@ exports[`Upload Data Set should display upload standard input help 1`] = ` DESCRIPTION ----------- - Upload the content of a stdin to a z/OS data set + Upload the content of a stdin to a z/OS data set. USAGE ----- @@ -174,8 +174,8 @@ exports[`Upload Data Set should display upload standard input help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: stdin-to-data-set.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n stdin-to-data-set | stds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload the content of a stdin to a z/OS data set\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload stdin-to-data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set to which you want to upload data\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --migrated-recall | --mr (string)\\\\n\\\\n The method by which migrated data set is handled. By default, a migrated data\\\\n set is recalled synchronously. You can specify the following values: wait,\\\\n nowait, error\\\\n\\\\n Default value: nowait\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Data content in record mode, which means that no data conversion is performed\\\\n and the record length is prepended to the data. The data transfer process\\\\n returns each line as-is, without translation. No delimiters are added between\\\\n records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Stream content from stdin to a sequential data set named\\\\n \\\\\\"ibmuser.ps\\\\\\" from a Windows console:\\\\n\\\\n $ echo \\\\\\"hello world\\\\\\" | zowe zos-files upload stdin-to-data-set \\\\\\"ibmuser.ps\\\\\\"\\\\n\\\\n - Stream content from stdin to a partition data set member\\\\n named \\\\\\"ibmuser.pds(mem)\\\\\\" from a Windows console:\\\\n\\\\n $ echo \\\\\\"hello world\\\\\\" | zowe zos-files upload stdin-to-data-set \\\\\\"ibmuser.pds(mem)\\\\\\"\\\\n\\\\n - Stream content from stdin to a migrated data set and wait\\\\n for it to be recalled from a Windows console:\\\\n\\\\n $ echo \\\\\\"hello world\\\\\\" | zowe zos-files upload stdin-to-data-set \\\\\\"ibmuser.ps\\\\\\" --mr wait\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n stdin-to-data-set | stds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload the content of a stdin to a z/OS data set.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload stdin-to-data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set to which you want to upload data\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --migrated-recall | --mr (string)\\\\n\\\\n The method by which migrated data set is handled. By default, a migrated data\\\\n set is recalled synchronously. You can specify the following values: wait,\\\\n nowait, error\\\\n\\\\n Default value: nowait\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Data content in record mode, which means that no data conversion is performed\\\\n and the record length is prepended to the data. The data transfer process\\\\n returns each line as-is, without translation. No delimiters are added between\\\\n records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Stream content from stdin to a sequential data set named\\\\n \\\\\\"ibmuser.ps\\\\\\" from a Windows console:\\\\n\\\\n $ echo \\\\\\"hello world\\\\\\" | zowe zos-files upload stdin-to-data-set \\\\\\"ibmuser.ps\\\\\\"\\\\n\\\\n - Stream content from stdin to a partition data set member\\\\n named \\\\\\"ibmuser.pds(mem)\\\\\\" from a Windows console:\\\\n\\\\n $ echo \\\\\\"hello world\\\\\\" | zowe zos-files upload stdin-to-data-set \\\\\\"ibmuser.pds(mem)\\\\\\"\\\\n\\\\n - Stream content from stdin to a migrated data set and wait\\\\n for it to be recalled from a Windows console:\\\\n\\\\n $ echo \\\\\\"hello world\\\\\\" | zowe zos-files upload stdin-to-data-set \\\\\\"ibmuser.ps\\\\\\" --mr wait\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n stdin-to-data-set | stds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload the content of a stdin to a z/OS data set\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload stdin-to-data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set to which you want to upload data\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --migrated-recall | --mr (string)\\\\n\\\\n The method by which migrated data set is handled. By default, a migrated data\\\\n set is recalled synchronously. You can specify the following values: wait,\\\\n nowait, error\\\\n\\\\n Default value: nowait\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Data content in record mode, which means that no data conversion is performed\\\\n and the record length is prepended to the data. The data transfer process\\\\n returns each line as-is, without translation. No delimiters are added between\\\\n records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Stream content from stdin to a sequential data set named\\\\n \\\\\\"ibmuser.ps\\\\\\" from a Windows console:\\\\n\\\\n $ echo \\\\\\"hello world\\\\\\" | zowe zos-files upload stdin-to-data-set \\\\\\"ibmuser.ps\\\\\\"\\\\n\\\\n - Stream content from stdin to a partition data set member\\\\n named \\\\\\"ibmuser.pds(mem)\\\\\\" from a Windows console:\\\\n\\\\n $ echo \\\\\\"hello world\\\\\\" | zowe zos-files upload stdin-to-data-set \\\\\\"ibmuser.pds(mem)\\\\\\"\\\\n\\\\n - Stream content from stdin to a migrated data set and wait\\\\n for it to be recalled from a Windows console:\\\\n\\\\n $ echo \\\\\\"hello world\\\\\\" | zowe zos-files upload stdin-to-data-set \\\\\\"ibmuser.ps\\\\\\" --mr wait\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n stdin-to-data-set | stds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Upload the content of a stdin to a z/OS data set.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files upload stdin-to-data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n dataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set to which you want to upload data\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --binary | -b (boolean)\\\\n\\\\n Data content in binary mode, which means that no data conversion is performed.\\\\n The data transfer process returns each record as-is, without translation. No\\\\n delimiters are added between records.\\\\n\\\\n --migrated-recall | --mr (string)\\\\n\\\\n The method by which migrated data set is handled. By default, a migrated data\\\\n set is recalled synchronously. You can specify the following values: wait,\\\\n nowait, error\\\\n\\\\n Default value: nowait\\\\n\\\\n --record | -r (boolean)\\\\n\\\\n Data content in record mode, which means that no data conversion is performed\\\\n and the record length is prepended to the data. The data transfer process\\\\n returns each line as-is, without translation. No delimiters are added between\\\\n records. Conflicts with binary.\\\\n\\\\n --volume-serial | --vs (string)\\\\n\\\\n The volume serial (VOLSER) where the data set resides. You can use this option\\\\n at any time. However, the VOLSER is required only when the data set is not\\\\n cataloged on the system. A VOLSER is analogous to a drive name on a PC.\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Stream content from stdin to a sequential data set named\\\\n \\\\\\"ibmuser.ps\\\\\\" from a Windows console:\\\\n\\\\n $ echo \\\\\\"hello world\\\\\\" | zowe zos-files upload stdin-to-data-set \\\\\\"ibmuser.ps\\\\\\"\\\\n\\\\n - Stream content from stdin to a partition data set member\\\\n named \\\\\\"ibmuser.pds(mem)\\\\\\" from a Windows console:\\\\n\\\\n $ echo \\\\\\"hello world\\\\\\" | zowe zos-files upload stdin-to-data-set \\\\\\"ibmuser.pds(mem)\\\\\\"\\\\n\\\\n - Stream content from stdin to a migrated data set and wait\\\\n for it to be recalled from a Windows console:\\\\n\\\\n $ echo \\\\\\"hello world\\\\\\" | zowe zos-files upload stdin-to-data-set \\\\\\"ibmuser.ps\\\\\\" --mr wait\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosfiles/__system__/create/binaryPds/__scripts__/command/command_create_binary_pds_with_primary.sh b/packages/cli/__tests__/zosfiles/__system__/create/binaryPds/__scripts__/command/command_create_binary_pds_with_primary.sh index 712fd4cb12..53db8b4638 100755 --- a/packages/cli/__tests__/zosfiles/__system__/create/binaryPds/__scripts__/command/command_create_binary_pds_with_primary.sh +++ b/packages/cli/__tests__/zosfiles/__system__/create/binaryPds/__scripts__/command/command_create_binary_pds_with_primary.sh @@ -3,7 +3,7 @@ hlq1=$1 set -e echo "================Z/OS FILES CREATE DATA-SET-BINARY===============" -zowe zos-files create data-set-binary "$1.test.data.set.binary.primary" --ps 20 --pa +zowe zos-files create data-set-binary "$1.test.data.set.binary.primary" --ps 20 --attributes if [ $? -gt 0 ] then exit $? diff --git a/packages/cli/__tests__/zosfiles/__system__/create/binaryPds/__scripts__/command/command_create_binary_pds_with_primary_secondary.sh b/packages/cli/__tests__/zosfiles/__system__/create/binaryPds/__scripts__/command/command_create_binary_pds_with_primary_secondary.sh index 1a583b6afe..0443d83e75 100755 --- a/packages/cli/__tests__/zosfiles/__system__/create/binaryPds/__scripts__/command/command_create_binary_pds_with_primary_secondary.sh +++ b/packages/cli/__tests__/zosfiles/__system__/create/binaryPds/__scripts__/command/command_create_binary_pds_with_primary_secondary.sh @@ -3,7 +3,7 @@ hlq1=$1 set -e echo "================Z/OS FILES CREATE DATA-SET-BINARY===============" -zowe zos-files create data-set-binary "$1.test.data.set.binary.second" --ps 20 --ss 5 --pa +zowe zos-files create data-set-binary "$1.test.data.set.binary.second" --ps 20 --ss 5 --attributes if [ $? -gt 0 ] then exit $? diff --git a/packages/cli/__tests__/zosfiles/__system__/create/binaryPds/__scripts__/command/command_create_binary_pds_with_size.sh b/packages/cli/__tests__/zosfiles/__system__/create/binaryPds/__scripts__/command/command_create_binary_pds_with_size.sh index 4971d94835..60425c28e2 100755 --- a/packages/cli/__tests__/zosfiles/__system__/create/binaryPds/__scripts__/command/command_create_binary_pds_with_size.sh +++ b/packages/cli/__tests__/zosfiles/__system__/create/binaryPds/__scripts__/command/command_create_binary_pds_with_size.sh @@ -3,7 +3,7 @@ hlq1=$1 set -e echo "================Z/OS FILES CREATE DATA-SET-BINARY===============" -zowe zos-files create data-set-partitioned "$1.test.data.set.binary.size" --size 2CYL --pa +zowe zos-files create data-set-partitioned "$1.test.data.set.binary.size" --size 2CYL --attributes if [ $? -gt 0 ] then exit $? diff --git a/packages/cli/__tests__/zosfiles/__system__/create/cPds/__scripts__/command/command_create_c_pds_with_primary.sh b/packages/cli/__tests__/zosfiles/__system__/create/cPds/__scripts__/command/command_create_c_pds_with_primary.sh index 25a8e458ce..79eef6d37b 100755 --- a/packages/cli/__tests__/zosfiles/__system__/create/cPds/__scripts__/command/command_create_c_pds_with_primary.sh +++ b/packages/cli/__tests__/zosfiles/__system__/create/cPds/__scripts__/command/command_create_c_pds_with_primary.sh @@ -3,7 +3,7 @@ hlq1=$1 set -e echo "================Z/OS FILES CREATE DATA-SET-C===============" -zowe zos-files create data-set-c "$1.test.data.set.c.primary" --ps 20 --pa +zowe zos-files create data-set-c "$1.test.data.set.c.primary" --ps 20 --attributes if [ $? -gt 0 ] then exit $? diff --git a/packages/cli/__tests__/zosfiles/__system__/create/cPds/__scripts__/command/command_create_c_pds_with_primary_secondary.sh b/packages/cli/__tests__/zosfiles/__system__/create/cPds/__scripts__/command/command_create_c_pds_with_primary_secondary.sh index 188e41d8a0..a21f936dbf 100755 --- a/packages/cli/__tests__/zosfiles/__system__/create/cPds/__scripts__/command/command_create_c_pds_with_primary_secondary.sh +++ b/packages/cli/__tests__/zosfiles/__system__/create/cPds/__scripts__/command/command_create_c_pds_with_primary_secondary.sh @@ -3,7 +3,7 @@ hlq1=$1 set -e echo "================Z/OS FILES CREATE DATA-SET-C===============" -zowe zos-files create data-set-c "$1.test.data.set.c.second" --ps 20 --ss 5 --pa +zowe zos-files create data-set-c "$1.test.data.set.c.second" --ps 20 --ss 5 --attributes if [ $? -gt 0 ] then exit $? diff --git a/packages/cli/__tests__/zosfiles/__system__/create/cPds/__scripts__/command/command_create_c_pds_with_size.sh b/packages/cli/__tests__/zosfiles/__system__/create/cPds/__scripts__/command/command_create_c_pds_with_size.sh index 818fcff915..adc39e47aa 100755 --- a/packages/cli/__tests__/zosfiles/__system__/create/cPds/__scripts__/command/command_create_c_pds_with_size.sh +++ b/packages/cli/__tests__/zosfiles/__system__/create/cPds/__scripts__/command/command_create_c_pds_with_size.sh @@ -3,7 +3,7 @@ hlq=$1 set -e echo "================Z/OS FILES CREATE DATA-SET-C===============" -zowe zos-files create data-set-c "$1.test.data.set.c.size" --size 2CYL --pa +zowe zos-files create data-set-c "$1.test.data.set.c.size" --size 2CYL --attributes if [ $? -gt 0 ] then exit $? diff --git a/packages/cli/__tests__/zosfiles/__system__/create/classicPds/__scripts__/command/command_create_classic_pds_with_primary.sh b/packages/cli/__tests__/zosfiles/__system__/create/classicPds/__scripts__/command/command_create_classic_pds_with_primary.sh index 71495c2a9e..3bc8e34753 100755 --- a/packages/cli/__tests__/zosfiles/__system__/create/classicPds/__scripts__/command/command_create_classic_pds_with_primary.sh +++ b/packages/cli/__tests__/zosfiles/__system__/create/classicPds/__scripts__/command/command_create_classic_pds_with_primary.sh @@ -3,7 +3,7 @@ hlq1=$1 set -e echo "================Z/OS FILES CREATE DATA-SET-CLASSIC===============" -zowe zos-files create data-set-classic "$1.test.data.set.classic.primary" --ps 20 --pa +zowe zos-files create data-set-classic "$1.test.data.set.classic.primary" --ps 20 --attributes if [ $? -gt 0 ] then exit $? diff --git a/packages/cli/__tests__/zosfiles/__system__/create/classicPds/__scripts__/command/command_create_classic_pds_with_primary_secondary.sh b/packages/cli/__tests__/zosfiles/__system__/create/classicPds/__scripts__/command/command_create_classic_pds_with_primary_secondary.sh index b81c1fa4dc..7e589a951a 100755 --- a/packages/cli/__tests__/zosfiles/__system__/create/classicPds/__scripts__/command/command_create_classic_pds_with_primary_secondary.sh +++ b/packages/cli/__tests__/zosfiles/__system__/create/classicPds/__scripts__/command/command_create_classic_pds_with_primary_secondary.sh @@ -3,7 +3,7 @@ hlq1=$1 set -e echo "================Z/OS FILES CREATE DATA-SET-CLASSIC===============" -zowe zos-files create data-set-classic "$1.test.data.set.classic.second" --ps 20 --ss 5 --pa +zowe zos-files create data-set-classic "$1.test.data.set.classic.second" --ps 20 --ss 5 --attributes if [ $? -gt 0 ] then exit $? diff --git a/packages/cli/__tests__/zosfiles/__system__/create/classicPds/__scripts__/command/command_create_classic_pds_with_size.sh b/packages/cli/__tests__/zosfiles/__system__/create/classicPds/__scripts__/command/command_create_classic_pds_with_size.sh index 32071cf8c7..c5d36eb152 100755 --- a/packages/cli/__tests__/zosfiles/__system__/create/classicPds/__scripts__/command/command_create_classic_pds_with_size.sh +++ b/packages/cli/__tests__/zosfiles/__system__/create/classicPds/__scripts__/command/command_create_classic_pds_with_size.sh @@ -3,7 +3,7 @@ hlq=$1 set -e echo "================Z/OS FILES CREATE DATA-SET-CLASSIC===============" -zowe zos-files create data-set-classic "$1.test.data.set.classic.size" --size 2CYL --pa +zowe zos-files create data-set-classic "$1.test.data.set.classic.size" --size 2CYL --attributes if [ $? -gt 0 ] then exit $? diff --git a/packages/cli/__tests__/zosfiles/__system__/create/pds/__scripts__/command/command_create_pds_with_primary.sh b/packages/cli/__tests__/zosfiles/__system__/create/pds/__scripts__/command/command_create_pds_with_primary.sh index 3c39a2f307..b4716dd149 100755 --- a/packages/cli/__tests__/zosfiles/__system__/create/pds/__scripts__/command/command_create_pds_with_primary.sh +++ b/packages/cli/__tests__/zosfiles/__system__/create/pds/__scripts__/command/command_create_pds_with_primary.sh @@ -3,7 +3,7 @@ hlq1=$1 set -e echo "================Z/OS FILES CREATE PDS===============" -zowe zos-files create pds "$1.test.data.set.pds.primary" --ps 20 --pa +zowe zos-files create pds "$1.test.data.set.pds.primary" --ps 20 --attributes if [ $? -gt 0 ] then exit $? diff --git a/packages/cli/__tests__/zosfiles/__system__/create/pds/__scripts__/command/command_create_pds_with_primary_secondary.sh b/packages/cli/__tests__/zosfiles/__system__/create/pds/__scripts__/command/command_create_pds_with_primary_secondary.sh index cd3162b07c..79af658c3a 100755 --- a/packages/cli/__tests__/zosfiles/__system__/create/pds/__scripts__/command/command_create_pds_with_primary_secondary.sh +++ b/packages/cli/__tests__/zosfiles/__system__/create/pds/__scripts__/command/command_create_pds_with_primary_secondary.sh @@ -3,7 +3,7 @@ hlq1=$1 set -e echo "================Z/OS FILES CREATE PDS===============" -zowe zos-files create pds "$1.test.data.set.pds.second" --ps 20 --ss 5 --pa +zowe zos-files create pds "$1.test.data.set.pds.second" --ps 20 --ss 5 --attributes if [ $? -gt 0 ] then exit $? diff --git a/packages/cli/__tests__/zosfiles/__system__/create/pds/__scripts__/command/command_create_pds_with_size.sh b/packages/cli/__tests__/zosfiles/__system__/create/pds/__scripts__/command/command_create_pds_with_size.sh index 45b322232a..ef06ef966c 100755 --- a/packages/cli/__tests__/zosfiles/__system__/create/pds/__scripts__/command/command_create_pds_with_size.sh +++ b/packages/cli/__tests__/zosfiles/__system__/create/pds/__scripts__/command/command_create_pds_with_size.sh @@ -3,7 +3,7 @@ hlq=$1 set -e echo "================Z/OS FILES CREATE PDS===============" -zowe zos-files create data-set-partitioned "$1.test.data.set.pds.size" --size 2CYL --pa +zowe zos-files create data-set-partitioned "$1.test.data.set.pds.size" --size 2CYL --attributes if [ $? -gt 0 ] then exit $? diff --git a/packages/cli/__tests__/zosfiles/__system__/create/pds/cli.files.create.dataset.pds.system.test.ts b/packages/cli/__tests__/zosfiles/__system__/create/pds/cli.files.create.dataset.pds.system.test.ts index 767560b62c..e550311677 100644 --- a/packages/cli/__tests__/zosfiles/__system__/create/pds/cli.files.create.dataset.pds.system.test.ts +++ b/packages/cli/__tests__/zosfiles/__system__/create/pds/cli.files.create.dataset.pds.system.test.ts @@ -216,7 +216,7 @@ describe("Create Partitioned Data Set", () => { it("should fail creating a partitioned data set due to invalid record format", () => { const response = runCliScript(__dirname + "/__scripts__/command/command_create_pds_fail_recfm.sh", TEST_ENVIRONMENT, [user]); - expect(response.stderr.toString()).toContain("Invalid zos-files create command 'recfm' option: NB"); + expect(response.stderr.toString()).toContain("Unable to perform this operation due to the following problem."); }); it("should fail creating a partitioned data set due to block size specified but no value specified", () => { diff --git a/packages/cli/__tests__/zosfiles/__system__/create/ps/__scripts__/command/command_create_ps_with_primary.sh b/packages/cli/__tests__/zosfiles/__system__/create/ps/__scripts__/command/command_create_ps_with_primary.sh index b1e4a24e91..4d458655d9 100755 --- a/packages/cli/__tests__/zosfiles/__system__/create/ps/__scripts__/command/command_create_ps_with_primary.sh +++ b/packages/cli/__tests__/zosfiles/__system__/create/ps/__scripts__/command/command_create_ps_with_primary.sh @@ -3,7 +3,7 @@ hlq1=$1 set -e echo "================Z/OS FILES CREATE DATA-SET-SEQUENTIAL===============" -zowe zos-files create data-set-sequential "$1.test.data.set.ps.primary" --ps 20 --pa +zowe zos-files create data-set-sequential "$1.test.data.set.ps.primary" --ps 20 --attributes if [ $? -gt 0 ] then exit $? diff --git a/packages/cli/__tests__/zosfiles/__system__/create/ps/__scripts__/command/command_create_ps_with_primary_secondary.sh b/packages/cli/__tests__/zosfiles/__system__/create/ps/__scripts__/command/command_create_ps_with_primary_secondary.sh index 053a05d570..b77c55f8b0 100755 --- a/packages/cli/__tests__/zosfiles/__system__/create/ps/__scripts__/command/command_create_ps_with_primary_secondary.sh +++ b/packages/cli/__tests__/zosfiles/__system__/create/ps/__scripts__/command/command_create_ps_with_primary_secondary.sh @@ -3,7 +3,7 @@ hlq1=$1 set -e echo "================Z/OS FILES CREATE DATA-SET-SEQUENTIAL===============" -zowe zos-files create data-set-sequential "$1.test.data.set.ps.second" --ps 20 --ss 5 --pa +zowe zos-files create data-set-sequential "$1.test.data.set.ps.second" --ps 20 --ss 5 --attributes if [ $? -gt 0 ] then exit $? diff --git a/packages/cli/__tests__/zosfiles/__system__/create/ps/__scripts__/command/command_create_ps_with_size.sh b/packages/cli/__tests__/zosfiles/__system__/create/ps/__scripts__/command/command_create_ps_with_size.sh index 4f928465bf..57c5c539ab 100755 --- a/packages/cli/__tests__/zosfiles/__system__/create/ps/__scripts__/command/command_create_ps_with_size.sh +++ b/packages/cli/__tests__/zosfiles/__system__/create/ps/__scripts__/command/command_create_ps_with_size.sh @@ -3,7 +3,7 @@ hlq=$1 set -e echo "================Z/OS FILES CREATE DATA-SET-SEQUENTIAL===============" -zowe zos-files create data-set-sequential "$1.test.data.set.ps.size" --size 2CYL --pa +zowe zos-files create data-set-sequential "$1.test.data.set.ps.size" --size 2CYL --attributes if [ $? -gt 0 ] then exit $? diff --git a/packages/cli/__tests__/zosfiles/__system__/search/ds/__scripts__/command_search_ds.sh b/packages/cli/__tests__/zosfiles/__system__/search/ds/__scripts__/command_search_ds.sh new file mode 100755 index 0000000000..bad43a0425 --- /dev/null +++ b/packages/cli/__tests__/zosfiles/__system__/search/ds/__scripts__/command_search_ds.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +DSN=$1 +STERM=$2 +shift 2 + +zowe zos-files search ds "$DSN" "$STERM" $@ +if [ $? -gt 0 ] +then + exit $? +fi diff --git a/packages/cli/__tests__/zosfiles/__system__/search/ds/__scripts__/command_search_ds_fully_qualified.sh b/packages/cli/__tests__/zosfiles/__system__/search/ds/__scripts__/command_search_ds_fully_qualified.sh new file mode 100755 index 0000000000..9fd5930779 --- /dev/null +++ b/packages/cli/__tests__/zosfiles/__system__/search/ds/__scripts__/command_search_ds_fully_qualified.sh @@ -0,0 +1,11 @@ +#!/bin/bash +DSN=$1 +STERM=$2 +HOST=$3 +PORT=$4 +USER=$5 +PASS=$6 +shift 6 + +zowe zos-files search ds "$DSN" "$STERM" --host $HOST --port $PORT --user $USER --password $PASS --ru=false $@ +exit $? \ No newline at end of file diff --git a/packages/cli/__tests__/zosfiles/__system__/search/ds/cli.files.search.ds.system.test.ts b/packages/cli/__tests__/zosfiles/__system__/search/ds/cli.files.search.ds.system.test.ts new file mode 100644 index 0000000000..cb5ee16471 --- /dev/null +++ b/packages/cli/__tests__/zosfiles/__system__/search/ds/cli.files.search.ds.system.test.ts @@ -0,0 +1,458 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { Session } from "@zowe/imperative"; +import * as path from "path"; +import { ITestEnvironment, runCliScript } from "@zowe/cli-test-utils"; +import { TestEnvironment } from "../../../../../../../__tests__/__src__/environment/TestEnvironment"; +import { ITestPropertiesSchema } from "../../../../../../../__tests__/__src__/properties/ITestPropertiesSchema"; +import { getUniqueDatasetName } from "../../../../../../../__tests__/__src__/TestUtils"; +import { Create, CreateDataSetTypeEnum, Delete, Upload } from "@zowe/zos-files-for-zowe-sdk"; + +let REAL_SESSION: Session; +// Test Environment populated in the beforeAll(); +let TEST_ENVIRONMENT: ITestEnvironment; +let TEST_ENVIRONMENT_NO_PROF: ITestEnvironment; +let defaultSystem: ITestPropertiesSchema; +let pattern: string; +let searchHLQ: string; +let dsnPrefix: string; + +let goodDsNames: string[]; +let badDsNames: string[]; + +let pdsNames: string[]; +let pdsGoodMemNames: string[]; +let pdsBadMemNames: string[]; + +let searchString = "Zowe CLI"; +let oldForceColor: string; + +const goodTestString = "This system test is brought to you by Zowe CLI!"; +const badTestString = "Sadly, this string will not match the search."; + +describe("Search Data Sets", () => { + beforeAll(async () => { + TEST_ENVIRONMENT = await TestEnvironment.setUp({ + tempProfileTypes: ["zosmf"], + testName: "search_data_sets" + }); + + defaultSystem = TEST_ENVIRONMENT.systemTestProperties; + REAL_SESSION = TestEnvironment.createZosmfSession(TEST_ENVIRONMENT); + searchHLQ = defaultSystem.zosmf.user + ".SEARCH"; + + oldForceColor = process.env.FORCE_COLOR; + process.env.FORCE_COLOR = "0"; + + dsnPrefix = getUniqueDatasetName(searchHLQ); + pattern = dsnPrefix + ".*"; + + goodDsNames = [`${dsnPrefix}.SEQ1`, `${dsnPrefix}.SEQ4`, `${dsnPrefix}.SEQ5`]; + badDsNames = [`${dsnPrefix}.SEQ2`, `${dsnPrefix}.SEQ3`]; + + pdsNames = [`${dsnPrefix}.PDS1`, `${dsnPrefix}.PDS2`]; + pdsGoodMemNames = ["MEM2", "MEM3"]; + pdsBadMemNames = ["MEM1", "MEM4"]; + + for (const dsn of [...goodDsNames, ...badDsNames]) { + await Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, dsn); + if (goodDsNames.includes(dsn)) { + await Upload.bufferToDataSet(REAL_SESSION, Buffer.from(goodTestString), `${dsn}`); + } else { + await Upload.bufferToDataSet(REAL_SESSION, Buffer.from(badTestString), `${dsn}`); + } + } + + for (const dsn of pdsNames) { + await Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_PARTITIONED, dsn); + for (const memname of pdsGoodMemNames) { + await Upload.bufferToDataSet(REAL_SESSION, Buffer.from(goodTestString), `${dsn}(${memname})`); + } + for (const memname of pdsBadMemNames) { + await Upload.bufferToDataSet(REAL_SESSION, Buffer.from(badTestString), `${dsn}(${memname})`); + } + } + }); + + afterAll(async () => { + process.env.FORCE_COLOR = oldForceColor; + for (const dsn of [...goodDsNames, ...badDsNames, ...pdsNames]) { + await Delete.dataSet(REAL_SESSION, dsn); + } + await TestEnvironment.cleanUp(TEST_ENVIRONMENT); + }); + + beforeEach(async () => { + searchString = "Zowe CLI"; + }); + + describe("without profiles", () => { + let defaultSys: ITestPropertiesSchema; + + // Create the unique test environment + beforeAll(async () => { + TEST_ENVIRONMENT_NO_PROF = await TestEnvironment.setUp({ + testName: "zos_files_search_ds_without_profile" + }); + + defaultSys = TEST_ENVIRONMENT_NO_PROF.systemTestProperties; + }); + + afterAll(async () => { + await TestEnvironment.cleanUp(TEST_ENVIRONMENT_NO_PROF); + }); + + const shellScript = path.join(__dirname, "__scripts__", "command_search_ds_fully_qualified.sh"); + + it("should search and find the correct data sets", async () => { + const response = runCliScript(shellScript, TEST_ENVIRONMENT_NO_PROF, [ + pattern, + searchString, + defaultSys.zosmf.host, + defaultSys.zosmf.port, + defaultSys.zosmf.user, + defaultSys.zosmf.password + ]); + + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.stdout.toString()).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should search and find the correct data sets rfj", async () => { + const response = runCliScript(shellScript, TEST_ENVIRONMENT_NO_PROF, [ + pattern, + searchString, + defaultSys.zosmf.host, + defaultSys.zosmf.port, + defaultSys.zosmf.user, + defaultSys.zosmf.password, + "--rfj" + ]); + const expectedApiResponse = [ + {dsn: `${dsnPrefix}.PDS1`, member: "MEM2", matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.PDS1`, member: "MEM3", matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.PDS2`, member: "MEM2", matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.PDS2`, member: "MEM3", matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.SEQ1`, matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.SEQ4`, matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.SEQ5`, matchList: [{line: 1, column: 39, contents: goodTestString}]}, + ]; + + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(JSON.parse(response.stdout.toString()).data.apiResponse).toEqual(expectedApiResponse); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should perform an initial mainframe search if requested", async () => { + const response = runCliScript(shellScript, TEST_ENVIRONMENT_NO_PROF, [ + pattern, + searchString, + defaultSys.zosmf.host, + defaultSys.zosmf.port, + defaultSys.zosmf.user, + defaultSys.zosmf.password, + "--mainframe-search" + ]); + + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.stdout.toString()).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should handle case sensitive searches 1", async () => { + const response = runCliScript(shellScript, TEST_ENVIRONMENT_NO_PROF, [ + pattern, + searchString, + defaultSys.zosmf.host, + defaultSys.zosmf.port, + defaultSys.zosmf.user, + defaultSys.zosmf.password, + "--case-sensitive" + ]); + + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.stdout.toString()).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should handle case sensitive searches 2", async () => { + searchString = "Zowe CLI".toLowerCase(); + const response = runCliScript(shellScript, TEST_ENVIRONMENT_NO_PROF, [ + pattern, + searchString, + defaultSys.zosmf.host, + defaultSys.zosmf.port, + defaultSys.zosmf.user, + defaultSys.zosmf.password, + "--case-sensitive" + ]); + + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain(`Found "${searchString}" in 0 data sets and PDS members`); + expect(response.stdout.toString()).not.toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.stdout.toString()).not.toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.stdout.toString()).not.toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.stdout.toString()).not.toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.stdout.toString()).not.toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.stdout.toString()).not.toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.stdout.toString()).not.toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.stdout.toString()).not.toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should allow for multiple concurrent requests", async () => { + const response = runCliScript(shellScript, TEST_ENVIRONMENT_NO_PROF, [ + pattern, + searchString, + defaultSys.zosmf.host, + defaultSys.zosmf.port, + defaultSys.zosmf.user, + defaultSys.zosmf.password, + "--max-concurrent-requests 2" + ]); + + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.stdout.toString()).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should time out after some time 1", async () => { + const response = runCliScript(shellScript, TEST_ENVIRONMENT_NO_PROF, [ + pattern, + searchString, + defaultSys.zosmf.host, + defaultSys.zosmf.port, + defaultSys.zosmf.user, + defaultSys.zosmf.password, + "--timeout 120" + ]); + + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.stdout.toString()).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should time out after some time 2", async () => { + const response = runCliScript(shellScript, TEST_ENVIRONMENT_NO_PROF, [ + pattern, + searchString, + defaultSys.zosmf.host, + defaultSys.zosmf.port, + defaultSys.zosmf.user, + defaultSys.zosmf.password, + "--timeout 1" + ]); + + /** + * Since this test is timeout based, we cannot make many assumptions about what will or will not be found. + * The safest assumption is that something may or may not be found, but we will not find everything + * in under one second. + */ + expect(response.status).toBe(1); + expect(response.stdout.toString()).toContain(`Found "${searchString}" in`); + expect(response.stdout.toString()).toContain(`data sets and PDS members`); + expect(response.stderr.toString()).toContain("The following data set(s) failed to be searched:"); + }); + + }); + + describe("with profiles", () => { + const shellScript = path.join(__dirname, "__scripts__", "command_search_ds.sh"); + + it("should search and find the correct data sets", async () => { + const response = runCliScript(shellScript, TEST_ENVIRONMENT, [pattern, searchString]); + + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.stdout.toString()).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should search and find the correct data sets rfj", async () => { + const response = runCliScript(shellScript, TEST_ENVIRONMENT, [pattern, searchString, "--rfj"]); + const expectedApiResponse = [ + {dsn: `${dsnPrefix}.PDS1`, member: "MEM2", matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.PDS1`, member: "MEM3", matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.PDS2`, member: "MEM2", matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.PDS2`, member: "MEM3", matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.SEQ1`, matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.SEQ4`, matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.SEQ5`, matchList: [{line: 1, column: 39, contents: goodTestString}]}, + ]; + + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(JSON.parse(response.stdout.toString()).data.apiResponse).toEqual(expectedApiResponse); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(JSON.parse(response.stdout.toString()).data.commandResponse).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should perform an initial mainframe search if requested", async () => { + const response = runCliScript(shellScript, TEST_ENVIRONMENT, [pattern, searchString, "--mainframe-search"]); + + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.stdout.toString()).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should handle case sensitive searches 1", async () => { + const response = runCliScript(shellScript, TEST_ENVIRONMENT, [pattern, searchString, "--case-sensitive"]); + + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.stdout.toString()).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should handle case sensitive searches 2", async () => { + searchString = "Zowe CLI".toLowerCase(); + const response = runCliScript(shellScript, TEST_ENVIRONMENT, [pattern, searchString, "--case-sensitive"]); + + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain(`Found "${searchString}" in 0 data sets and PDS members`); + expect(response.stdout.toString()).not.toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.stdout.toString()).not.toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.stdout.toString()).not.toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.stdout.toString()).not.toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.stdout.toString()).not.toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.stdout.toString()).not.toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.stdout.toString()).not.toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.stdout.toString()).not.toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should allow for multiple concurrent requests", async () => { + const response = runCliScript(shellScript, TEST_ENVIRONMENT, [pattern, searchString, "--max-concurrent-requests 2"]); + + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.stdout.toString()).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should time out after some time 1", async () => { + const response = runCliScript(shellScript, TEST_ENVIRONMENT, [pattern, searchString, "--timeout 120"]); + + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.stdout.toString()).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.stdout.toString()).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should time out after some time 2", async () => { + const response = runCliScript(shellScript, TEST_ENVIRONMENT, [pattern, searchString, "--timeout 1"]); + + /** + * Since this test is timeout based, we cannot make many assumptions about what will or will not be found. + * The safest assumption is that something may or may not be found, but we will not find everything + * in under one second. + */ + expect(response.status).toBe(1); + expect(response.stdout.toString()).toContain(`Found "${searchString}" in`); + expect(response.stdout.toString()).toContain(`data sets and PDS members`); + expect(response.stderr.toString()).toContain("The following data set(s) failed to be searched:"); + }); + }); +}); diff --git a/packages/cli/__tests__/zosfiles/__system__/upload/ftds/cli.files.upload.ftds.system.test.ts b/packages/cli/__tests__/zosfiles/__system__/upload/ftds/cli.files.upload.ftds.system.test.ts index 72f3092dab..61b73755a1 100644 --- a/packages/cli/__tests__/zosfiles/__system__/upload/ftds/cli.files.upload.ftds.system.test.ts +++ b/packages/cli/__tests__/zosfiles/__system__/upload/ftds/cli.files.upload.ftds.system.test.ts @@ -330,7 +330,7 @@ describe("Upload file to data set", () => { localFileName, "MF.DOES.NOT.EXIST" ]); - expect(response.stderr.toString()).toContain("Data set not found"); + expect(response.stderr.toString()).toContain("NOT IN CATALOG OR CATALOG CAN NOT BE ACCESSED"); }); }); }); diff --git a/packages/cli/__tests__/zosfiles/__unit__/ZosFilesBase.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/ZosFilesBase.handler.unit.test.ts index 3167faaa92..3bf71d36e7 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/ZosFilesBase.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/ZosFilesBase.handler.unit.test.ts @@ -9,7 +9,7 @@ * */ -import { AbstractSession, IHandlerParameters, IProfile, Session } from "@zowe/imperative"; +import { AbstractSession, IHandlerParameters, Session } from "@zowe/imperative"; import { IZosFilesResponse } from "@zowe/zos-files-for-zowe-sdk"; import { ZosFilesBaseHandler } from "../../../src/zosfiles/ZosFilesBase.handler"; @@ -21,8 +21,7 @@ describe("ZosFilesBaseHandler", () => { public async processWithSession( commandParameters: IHandlerParameters, - session: AbstractSession, - zosmfProfile: IProfile + session: AbstractSession ): Promise { return this.returnResponse; } diff --git a/packages/cli/__tests__/zosfiles/__unit__/compare/CompareBaseHelper.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/compare/CompareBaseHelper.unit.test.ts index ff721bd54a..545fdadf55 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/compare/CompareBaseHelper.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/compare/CompareBaseHelper.unit.test.ts @@ -44,7 +44,7 @@ describe("Compare Base Helper", () => { return "compared string"; }); helper.getResponse(string1, string2); - expect(DiffUtils.getDiffString).toBeCalled(); + expect(DiffUtils.getDiffString).toHaveBeenCalled(); }); @@ -52,8 +52,8 @@ describe("Compare Base Helper", () => { helper.browserView = true; jest.spyOn(DiffUtils, "openDiffInbrowser").mockImplementation(jest.fn()); helper.getResponse(string1, string2); - expect(DiffUtils.openDiffInbrowser).toBeCalled(); - expect(DiffUtils.openDiffInbrowser).toBeCalledWith(string1, string2, undefined); + expect(DiffUtils.openDiffInbrowser).toHaveBeenCalled(); + expect(DiffUtils.openDiffInbrowser).toHaveBeenCalledWith(string1, string2, undefined); }); }); diff --git a/packages/cli/__tests__/zosfiles/__unit__/compare/ds/Dataset.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/compare/ds/Dataset.handler.unit.test.ts index 74d90159a8..c831d710a5 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/compare/ds/Dataset.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/compare/ds/Dataset.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Get } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { DiffUtils, IDiffOptions, ImperativeError } from "@zowe/imperative"; describe("Compare data set handler", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/compare/ds/__snapshots__/Dataset.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/compare/ds/__snapshots__/Dataset.definition.unit.test.ts.snap index a0f683f9fb..d6499060de 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/compare/ds/__snapshots__/Dataset.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/compare/ds/__snapshots__/Dataset.definition.unit.test.ts.snap @@ -6,7 +6,7 @@ Array [ "aliases": Array [ "b", ], - "description": "Transfer the content of the first data set in binary mode (no EBCDIC to ASCII conversion). If binary mode is set and the binary2 flag is not set then both datasets are transferred in binary mode.", + "description": "Transfer the content of the first data set in binary mode (no EBCDIC to ASCII conversion). If binary mode is set and the binary2 flag is not set then both data sets are transferred in binary mode.", "name": "binary", "type": "boolean", }, @@ -93,7 +93,7 @@ Array [ "aliases": Array [ "bv", ], - "description": "Opens the diffs between two given files in browser", + "description": "Opens the diffs between two given files in browser.", "name": "browser-view", "type": "boolean", }, diff --git a/packages/cli/__tests__/zosfiles/__unit__/compare/lf-ds/LocalfileDataset.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/compare/lf-ds/LocalfileDataset.handler.unit.test.ts index 108b0544fc..c5f1f32ccb 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/compare/lf-ds/LocalfileDataset.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/compare/lf-ds/LocalfileDataset.handler.unit.test.ts @@ -12,7 +12,7 @@ jest.mock("fs"); import { Get } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { DiffUtils, IDiffOptions, ImperativeError } from "@zowe/imperative"; import * as fs from "fs"; describe("Compare local-file and data-set handler", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/compare/lf-ds/__snapshots__/LocalfileDataset.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/compare/lf-ds/__snapshots__/LocalfileDataset.definition.unit.test.ts.snap index 0d4fa19f8a..68d4509553 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/compare/lf-ds/__snapshots__/LocalfileDataset.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/compare/lf-ds/__snapshots__/LocalfileDataset.definition.unit.test.ts.snap @@ -6,7 +6,7 @@ Array [ "aliases": Array [ "b", ], - "description": "Transfer the content of the first data set in binary mode (no EBCDIC to ASCII conversion). If binary mode is set and the binary2 flag is not set then both datasets are transferred in binary mode.", + "description": "Transfer the content of the first data set in binary mode (no EBCDIC to ASCII conversion). If binary mode is set and the binary2 flag is not set then both data sets are transferred in binary mode.", "name": "binary", "type": "boolean", }, @@ -58,7 +58,7 @@ Array [ "aliases": Array [ "bv", ], - "description": "Opens the diffs between two given files in browser", + "description": "Opens the diffs between two given files in browser.", "name": "browser-view", "type": "boolean", }, @@ -72,7 +72,7 @@ Array [ "options": "\\"./a.txt\\" \\"sys1.samplib(antxtso)\\"", }, Object { - "description": "Compare the contents of the local file and the data set member \\"./a.txt\\" and \\"sys1.samplib(antxtso)\\"without sequence numbers", + "description": "Compare the contents of the local file and the data set member \\"./a.txt\\" and \\"sys1.samplib(antxtso)\\" without sequence numbers", "options": "\\"./a.txt\\" \\"sys1.samplib(antxtso)\\" --no-seqnum", }, ] diff --git a/packages/cli/__tests__/zosfiles/__unit__/compare/lf-sdd/LocalfileSpooldd.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/compare/lf-sdd/LocalfileSpooldd.handler.unit.test.ts index 79eadc9972..e7c137a664 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/compare/lf-sdd/LocalfileSpooldd.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/compare/lf-sdd/LocalfileSpooldd.handler.unit.test.ts @@ -12,7 +12,7 @@ jest.mock("fs"); import { GetJobs } from "@zowe/zos-jobs-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { DiffUtils, IDiffOptions, ImperativeError } from "@zowe/imperative"; import * as fs from "fs"; diff --git a/packages/cli/__tests__/zosfiles/__unit__/compare/lf-sdd/__snapshots__/LocalfileSpooldd.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/compare/lf-sdd/__snapshots__/LocalfileSpooldd.definition.unit.test.ts.snap index 984258e108..1603b58f14 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/compare/lf-sdd/__snapshots__/LocalfileSpooldd.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/compare/lf-sdd/__snapshots__/LocalfileSpooldd.definition.unit.test.ts.snap @@ -23,7 +23,7 @@ Array [ "aliases": Array [ "bv", ], - "description": "Opens the diffs between two given files in browser", + "description": "Opens the diffs between two given files in browser.", "name": "browser-view", "type": "boolean", }, @@ -37,7 +37,7 @@ Array [ "options": "\\"./a.txt\\" \\"jobName:jobId:spoolId\\"", }, Object { - "description": "Compare the contents of a local-file and a spool dd \\"./a.txt\\" \\"jobName:jobId:spoolId\\"without sequence numbers", + "description": "Compare the contents of a local-file and a spool dd \\"./a.txt\\" \\"jobName:jobId:spoolId\\" without sequence numbers", "options": "\\"./a.txt\\" \\"jobName:jobId:spoolId\\" --no-seqnum", }, ] diff --git a/packages/cli/__tests__/zosfiles/__unit__/compare/lf-uss/LocalfileUss.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/compare/lf-uss/LocalfileUss.handler.unit.test.ts index 2fd4591f18..567d13e921 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/compare/lf-uss/LocalfileUss.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/compare/lf-uss/LocalfileUss.handler.unit.test.ts @@ -12,7 +12,7 @@ jest.mock("fs"); import { Get } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { DiffUtils, IDiffOptions } from "@zowe/imperative"; import * as fs from "fs"; diff --git a/packages/cli/__tests__/zosfiles/__unit__/compare/lf-uss/__snapshots__/LocalfileUss.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/compare/lf-uss/__snapshots__/LocalfileUss.definition.unit.test.ts.snap index 87149f2954..5d61de9a25 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/compare/lf-uss/__snapshots__/LocalfileUss.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/compare/lf-uss/__snapshots__/LocalfileUss.definition.unit.test.ts.snap @@ -6,7 +6,7 @@ Array [ "aliases": Array [ "b", ], - "description": "Transfer the content of the first data set in binary mode (no EBCDIC to ASCII conversion). If binary mode is set and the binary2 flag is not set then both datasets are transferred in binary mode.", + "description": "Transfer the content of the first data set in binary mode (no EBCDIC to ASCII conversion). If binary mode is set and the binary2 flag is not set then both data sets are transferred in binary mode.", "name": "binary", "type": "boolean", }, @@ -39,7 +39,7 @@ Array [ "aliases": Array [ "bv", ], - "description": "Opens the diffs between two given files in browser", + "description": "Opens the diffs between two given files in browser.", "name": "browser-view", "type": "boolean", }, @@ -49,11 +49,11 @@ Array [ exports[`zos-files compare lfuss command definition should not have changed 2`] = ` Array [ Object { - "description": "Compare the contents of the local file and the uss file \\"./a.txt\\" and \\"/u/user/test.txt\\"", + "description": "Compare the contents of the local file and the USS file \\"./a.txt\\" and \\"/u/user/test.txt\\"", "options": "\\"./a.txt\\" \\"/u/user/test.txt\\"", }, Object { - "description": "Compare the contents of the local file and the uss file \\"./a.txt\\" and \\"/u/user/test.txt\\"without sequence numbers", + "description": "Compare the contents of the local file and the USS file \\"./a.txt\\" and \\"/u/user/test.txt\\" without sequence numbers", "options": "\\"./a.txt\\" \\"/u/user/test.txt\\" --no-seqnum", }, ] diff --git a/packages/cli/__tests__/zosfiles/__unit__/compare/sdd/Spooldd.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/compare/sdd/Spooldd.handler.unit.test.ts index d71b72dd4f..9b71ec2b96 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/compare/sdd/Spooldd.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/compare/sdd/Spooldd.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { GetJobs } from "@zowe/zos-jobs-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { DiffUtils, IDiffOptions, ImperativeError } from "@zowe/imperative"; describe("Compare spooldd handler", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/compare/sdd/__snapshots__/Spooldd.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/compare/sdd/__snapshots__/Spooldd.definition.unit.test.ts.snap index 8d3537e11d..d867a1fc48 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/compare/sdd/__snapshots__/Spooldd.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/compare/sdd/__snapshots__/Spooldd.definition.unit.test.ts.snap @@ -14,7 +14,7 @@ Array [ "aliases": Array [ "bv", ], - "description": "Opens the diffs between two given files in browser", + "description": "Opens the diffs between two given files in browser.", "name": "browser-view", "type": "boolean", }, @@ -28,7 +28,7 @@ Array [ "options": "\\"jobName1:jobId1:spoolId1\\" \\"jobName2:jobId2:spoolId2\\"", }, Object { - "description": "Compare the contents of the two spool dds \\"jobName1:jobId1:spoolId1\\" \\"jobName2:jobId2:spoolId2\\"without sequence numbers", + "description": "Compare the contents of the two spool dds \\"jobName1:jobId1:spoolId1\\" \\"jobName2:jobId2:spoolId2\\" without sequence numbers", "options": "\\"jobName1:jobId1:spoolId1\\" \\"jobName2:jobId2:spoolId2\\" --no-seqnum", }, ] diff --git a/packages/cli/__tests__/zosfiles/__unit__/compare/uss/UssFile.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/compare/uss/UssFile.handler.unit.test.ts index de4ac64f24..8117ec2719 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/compare/uss/UssFile.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/compare/uss/UssFile.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Get } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { DiffUtils, IDiffOptions, ImperativeError } from "@zowe/imperative"; describe("Compare data set handler", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/compare/uss/__snapshots__/UssFile.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/compare/uss/__snapshots__/UssFile.definition.unit.test.ts.snap index 0da21e519a..286bd11fe2 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/compare/uss/__snapshots__/UssFile.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/compare/uss/__snapshots__/UssFile.definition.unit.test.ts.snap @@ -6,7 +6,7 @@ Array [ "aliases": Array [ "b", ], - "description": "Transfer the content of the first data set in binary mode (no EBCDIC to ASCII conversion). If binary mode is set and the binary2 flag is not set then both datasets are transferred in binary mode.", + "description": "Transfer the content of the first data set in binary mode (no EBCDIC to ASCII conversion). If binary mode is set and the binary2 flag is not set then both data sets are transferred in binary mode.", "name": "binary", "type": "boolean", }, @@ -55,7 +55,7 @@ Array [ "aliases": Array [ "bv", ], - "description": "Opens the diffs between two given files in browser", + "description": "Opens the diffs between two given files in browser.", "name": "browser-view", "type": "boolean", }, @@ -65,11 +65,11 @@ Array [ exports[`zos-files compare uss command definition should not have changed 2`] = ` Array [ Object { - "description": "Compare the contents of the uss file \\"/u/user/test.txt\\" and \\"/u/user/test.txt\\"", + "description": "Compare the contents of the USS file \\"/u/user/test.txt\\" and \\"/u/user/test.txt\\"", "options": "\\"/u/user/test.txt\\" \\"/u/user/test.txt\\"", }, Object { - "description": "Compare the contents of the uss file \\"/u/user/test.txt\\" and \\"/u/user/test.txt\\" without sequence numbers", + "description": "Compare the contents of the USS file \\"/u/user/test.txt\\" and \\"/u/user/test.txt\\" without sequence numbers", "options": "\\"/u/user/test.txt\\" \\"/u/user/test.txt\\" --no-seqnum", }, ] diff --git a/packages/cli/__tests__/zosfiles/__unit__/copy/ds/__snapshots__/Ds.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/copy/ds/__snapshots__/Ds.definition.unit.test.ts.snap index 6a8ad19cb2..cee4e8287e 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/copy/ds/__snapshots__/Ds.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/copy/ds/__snapshots__/Ds.definition.unit.test.ts.snap @@ -6,7 +6,7 @@ Array [ "aliases": Array [ "rep", ], - "description": "Specify this option as true if you wish to replace like-named members in the target dataset", + "description": "Specify this option as true if you wish to replace like-named members in the target data set", "name": "replace", "type": "boolean", }, diff --git a/packages/cli/__tests__/zosfiles/__unit__/copy/dsclp/TargetProfile.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/copy/dsclp/TargetProfile.handler.unit.test.ts index a31b176399..9feccd3f0f 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/copy/dsclp/TargetProfile.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/copy/dsclp/TargetProfile.handler.unit.test.ts @@ -12,17 +12,13 @@ import { IHandlerParameters, ImperativeConfig, ImperativeError } from "@zowe/imperative"; import TargetProfileHandler from "../../../../../src/zosfiles/copy/dsclp/TargetProfile.handler"; import { DsclpDefinition } from "../../../../../src/zosfiles/copy/dsclp/Dsclp.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["files", "copy", "data-set-cross-lpar"], - definition: DsclpDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: DsclpDefinition }); describe("TargetProfileHandler", () => { @@ -79,48 +75,6 @@ describe("TargetProfileHandler", () => { }); }); - it("should merge properties from v1 profiles and command arguments", async () => { - const commandParameters = { - ...DEFAULT_PARAMETERS, - arguments: { - ...DEFAULT_PARAMETERS.arguments, - host: "example1.com", - user: "user1", - password: "password1", - targetUser: "user2", - targetPassword: "password3", - targetZosmfProfile: "target_zosmf" - } - }; - - commandParameters.response.data.setObj = jest.fn(); - const getProfileMock = jest.fn().mockReturnValue({ - password: "password2", - port: 123 - }); - // eslint-disable-next-line deprecation/deprecation - commandParameters.profiles.get = getProfileMock; - jest.spyOn(ImperativeConfig, "instance", "get").mockReturnValue({ - config: { exists: false } - } as any); - - const handler = new TargetProfileHandler(); - await handler.process(commandParameters); - - expect(getProfileMock).toHaveBeenCalledTimes(1); - expect(commandParameters.response.data.setObj).toHaveBeenCalledWith({ - apiResponse: { - sessCfg: expect.objectContaining({ - hostname: "example1.com", - port: 123, - user: "user2", - password: "password3" - }) - }, - success: true - }); - }); - it("should handle error loading target z/OSMF profile", async () => { const commandParameters = { ...DEFAULT_PARAMETERS, diff --git a/packages/cli/__tests__/zosfiles/__unit__/copy/dsclp/__snapshots__/Dsclp.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/copy/dsclp/__snapshots__/Dsclp.definition.unit.test.ts.snap index 552958b81d..ce6568b172 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/copy/dsclp/__snapshots__/Dsclp.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/copy/dsclp/__snapshots__/Dsclp.definition.unit.test.ts.snap @@ -6,7 +6,7 @@ Array [ "aliases": Array [ "rep", ], - "description": "Specify this option as true if you wish to replace the target dataset if it already exists", + "description": "Specify this option as true if you wish to replace the target data set if it already exists.", "name": "replace", "type": "boolean", }, @@ -96,7 +96,7 @@ Array [ "t-zosmf-p", "target-zosmf-p", ], - "description": "The name of a z/OSMF profile to load for the target host. ", + "description": "The name of a z/OSMF profile to load for the target host.", "name": "target-zosmf-profile", "type": "string", }, diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/binaryPds/BinaryPDS.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/create/binaryPds/BinaryPDS.handler.unit.test.ts index 04231126d3..44c96a8651 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/binaryPds/BinaryPDS.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/create/binaryPds/BinaryPDS.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Create, CreateDataSetTypeEnum } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Create binary PDS data set handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/binaryPds/__snapshots__/BinaryPDS.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/create/binaryPds/__snapshots__/BinaryPDS.definition.unit.test.ts.snap index 3d78f02d2b..ce008558a5 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/binaryPds/__snapshots__/BinaryPDS.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/create/binaryPds/__snapshots__/BinaryPDS.definition.unit.test.ts.snap @@ -101,15 +101,6 @@ Array [ "name": "secondary-space", "type": "number", }, - Object { - "aliases": Array [ - "pa", - ], - "description": "Show the full allocation attributes", - "hidden": true, - "name": "show-attributes", - "type": "boolean", - }, Object { "aliases": Array [ "sz", diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/cPds/CPDS.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/create/cPds/CPDS.handler.unit.test.ts index 52ea562e68..56b9800230 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/cPds/CPDS.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/create/cPds/CPDS.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Create, CreateDataSetTypeEnum } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Create C-code PDS data set handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/cPds/__snapshots__/CPDS.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/create/cPds/__snapshots__/CPDS.definition.unit.test.ts.snap index f8a673e648..a4a1b4e452 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/cPds/__snapshots__/CPDS.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/create/cPds/__snapshots__/CPDS.definition.unit.test.ts.snap @@ -101,15 +101,6 @@ Array [ "name": "secondary-space", "type": "number", }, - Object { - "aliases": Array [ - "pa", - ], - "description": "Show the full allocation attributes", - "hidden": true, - "name": "show-attributes", - "type": "boolean", - }, Object { "aliases": Array [ "sz", diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/classicPds/ClassicPDS.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/create/classicPds/ClassicPDS.handler.unit.test.ts index 100a1f0269..6bf9932aa7 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/classicPds/ClassicPDS.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/create/classicPds/ClassicPDS.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Create, CreateDataSetTypeEnum } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Create classic PDS data set handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/classicPds/__snapshots__/ClassicPDS.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/create/classicPds/__snapshots__/ClassicPDS.definition.unit.test.ts.snap index 25c9e5899f..564896b1de 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/classicPds/__snapshots__/ClassicPDS.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/create/classicPds/__snapshots__/ClassicPDS.definition.unit.test.ts.snap @@ -101,15 +101,6 @@ Array [ "name": "secondary-space", "type": "number", }, - Object { - "aliases": Array [ - "pa", - ], - "description": "Show the full allocation attributes", - "hidden": true, - "name": "show-attributes", - "type": "boolean", - }, Object { "aliases": Array [ "sz", diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/ds/__snapshots__/ds.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/create/ds/__snapshots__/ds.definition.unit.test.ts.snap index b5f9f547ef..73bb2996a7 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/ds/__snapshots__/ds.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/create/ds/__snapshots__/ds.definition.unit.test.ts.snap @@ -104,15 +104,6 @@ Array [ "name": "secondary-space", "type": "number", }, - Object { - "aliases": Array [ - "pa", - ], - "description": "Show the full allocation attributes", - "hidden": true, - "name": "show-attributes", - "type": "boolean", - }, Object { "aliases": Array [ "sz", diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/ds/ds.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/create/ds/ds.handler.unit.test.ts index 1c8ce8705e..998ca33757 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/ds/ds.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/create/ds/ds.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Create, CreateDataSetTypeEnum } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Create data set handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/pds/Pds.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/create/pds/Pds.handler.unit.test.ts index 2f389193ac..d59d95b08b 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/pds/Pds.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/create/pds/Pds.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Create, CreateDataSetTypeEnum } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Create PDS data set handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/pds/__snapshots__/Pds.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/create/pds/__snapshots__/Pds.definition.unit.test.ts.snap index 25759dafb0..d026e7aca5 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/pds/__snapshots__/Pds.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/create/pds/__snapshots__/Pds.definition.unit.test.ts.snap @@ -110,15 +110,6 @@ Array [ "name": "secondary-space", "type": "number", }, - Object { - "aliases": Array [ - "pa", - ], - "description": "Show the full allocation attributes", - "hidden": true, - "name": "show-attributes", - "type": "boolean", - }, Object { "aliases": Array [ "sz", diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/ps/Ps.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/create/ps/Ps.handler.unit.test.ts index e830b6cf71..0ebd8da55e 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/ps/Ps.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/create/ps/Ps.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Create, CreateDataSetTypeEnum } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Create PS data set handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/ps/__snapshots__/Ps.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/create/ps/__snapshots__/Ps.definition.unit.test.ts.snap index e12c74ab33..aa73985c57 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/ps/__snapshots__/Ps.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/create/ps/__snapshots__/Ps.definition.unit.test.ts.snap @@ -91,15 +91,6 @@ Array [ "name": "secondary-space", "type": "number", }, - Object { - "aliases": Array [ - "pa", - ], - "description": "Show the full allocation attributes", - "hidden": true, - "name": "show-attributes", - "type": "boolean", - }, Object { "aliases": Array [ "sz", diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/ussDir/ussDir.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/create/ussDir/ussDir.handler.unit.test.ts index 299a0b6d28..8062b8d143 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/ussDir/ussDir.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/create/ussDir/ussDir.handler.unit.test.ts @@ -11,7 +11,7 @@ import { Create, IZosFilesOptions } from "@zowe/zos-files-for-zowe-sdk"; // import { CreateDataSetTypeEnum } from "../../../../src/api/methods/create/CreateDataSetType.enum"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Create USS Directory", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/ussFile/ussFile.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/create/ussFile/ussFile.handler.unit.test.ts index 765570d70d..05ebca4e72 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/ussFile/ussFile.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/create/ussFile/ussFile.handler.unit.test.ts @@ -11,7 +11,7 @@ import { Create, IZosFilesOptions } from "@zowe/zos-files-for-zowe-sdk"; // import { CreateDataSetTypeEnum } from "../../../../src/api/methods/create/CreateDataSetType.enum"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Create USS file", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/vsam/Vsam.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/create/vsam/Vsam.handler.unit.test.ts index 85a782fde4..cdcdf06c1d 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/vsam/Vsam.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/create/vsam/Vsam.handler.unit.test.ts @@ -11,7 +11,7 @@ import { Create } from "@zowe/zos-files-for-zowe-sdk"; import { ImperativeError } from "@zowe/imperative"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; const message: string = "Dummy error message"; diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/vsam/__snapshots__/Vsam.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/create/vsam/__snapshots__/Vsam.definition.unit.test.ts.snap index 88db998aad..4759888ba2 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/vsam/__snapshots__/Vsam.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/create/vsam/__snapshots__/Vsam.definition.unit.test.ts.snap @@ -80,15 +80,6 @@ Array [ "name": "secondary-space", "type": "number", }, - Object { - "aliases": Array [ - "pa", - ], - "description": "Show the full allocation attributes", - "hidden": true, - "name": "show-attributes", - "type": "boolean", - }, Object { "aliases": Array [ "sz", diff --git a/packages/cli/__tests__/zosfiles/__unit__/create/zfs/zfs.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/create/zfs/zfs.handler.unit.test.ts index 2c789f1fc7..d206a06c20 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/create/zfs/zfs.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/create/zfs/zfs.handler.unit.test.ts @@ -11,7 +11,7 @@ import { Create } from "@zowe/zos-files-for-zowe-sdk"; import { ImperativeError } from "@zowe/imperative"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; const message: string = "Dummy error message"; diff --git a/packages/cli/__tests__/zosfiles/__unit__/download/am/AllMembers.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/download/am/AllMembers.handler.unit.test.ts index f838bc33a1..42a1e5352b 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/download/am/AllMembers.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/download/am/AllMembers.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Download } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Download AllMembers handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/download/am/__snapshots__/AllMembers.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/download/am/__snapshots__/AllMembers.definition.unit.test.ts.snap index b5558119bc..077baf7c9c 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/download/am/__snapshots__/AllMembers.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/download/am/__snapshots__/AllMembers.definition.unit.test.ts.snap @@ -39,7 +39,7 @@ Array [ "ff", ], "defaultValue": true, - "description": "Set this option to false to continue downloading dataset members if one or more fail.", + "description": "Set this option to false to continue downloading data set members if one or more fail.", "name": "fail-fast", "type": "boolean", }, @@ -53,7 +53,7 @@ The maximum number of TSO address spaces have been created. When you specify 0, "name": "max-concurrent-requests", "numericValueRange": Array [ 0, - 99999, + 100, ], "type": "number", }, @@ -62,7 +62,7 @@ The maximum number of TSO address spaces have been created. When you specify 0, "po", ], "defaultValue": false, - "description": "Specifies if the automatically generated directories and files use the original letter case", + "description": "Specifies if the automatically generated directories and files use the original letter case.", "name": "preserve-original-letter-case", "type": "boolean", }, diff --git a/packages/cli/__tests__/zosfiles/__unit__/download/ds/Dataset.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/download/ds/Dataset.handler.unit.test.ts index 372231a04e..0bc6a28354 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/download/ds/Dataset.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/download/ds/Dataset.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Download } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Download data set handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/download/ds/__snapshots__/Dataset.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/download/ds/__snapshots__/Dataset.definition.unit.test.ts.snap index b0de96b836..5722077e2b 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/download/ds/__snapshots__/Dataset.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/download/ds/__snapshots__/Dataset.definition.unit.test.ts.snap @@ -39,7 +39,7 @@ Array [ "po", ], "defaultValue": false, - "description": "Specifies if the automatically generated directories and files use the original letter case", + "description": "Specifies if the automatically generated directories and files use the original letter case.", "name": "preserve-original-letter-case", "type": "boolean", }, diff --git a/packages/cli/__tests__/zosfiles/__unit__/download/dsm/DataSetMatching.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/download/dsm/DataSetMatching.handler.unit.test.ts index a2ec475ef9..ce1ae9cb95 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/download/dsm/DataSetMatching.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/download/dsm/DataSetMatching.handler.unit.test.ts @@ -13,14 +13,13 @@ import { IHandlerParameters, Session } from "@zowe/imperative"; import { Download, IDownloadOptions, IDsmListOptions, List } from "@zowe/zos-files-for-zowe-sdk"; import * as DataSetMatchingDefinition from "../../../../../src/zosfiles/download/dsm/DataSetMatching.definition"; import * as DataSetMatchingHandler from "../../../../../src/zosfiles/download/dsm/DataSetMatching.handler"; -import { UNIT_TEST_ZOSMF_PROF_OPTS, UNIT_TEST_PROFILES_ZOSMF } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-jobs", "download", "output"], - definition: DataSetMatchingDefinition.DataSetMatchingDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: DataSetMatchingDefinition.DataSetMatchingDefinition }); const fakeListOptions: IDsmListOptions = { @@ -35,7 +34,6 @@ const fakeDownloadOptions: IDownloadOptions = { binary: undefined, directory: undefined, encoding: undefined, - excludePatterns: undefined, extension: undefined, extensionMap: undefined, failFast: undefined, diff --git a/packages/cli/__tests__/zosfiles/__unit__/download/dsm/__snapshots__/DataSetMatching.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/download/dsm/__snapshots__/DataSetMatching.definition.unit.test.ts.snap index 9f784aba6c..17d48491f9 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/download/dsm/__snapshots__/DataSetMatching.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/download/dsm/__snapshots__/DataSetMatching.definition.unit.test.ts.snap @@ -58,7 +58,7 @@ Array [ "ff", ], "defaultValue": true, - "description": "Set this option to false to continue downloading dataset members if one or more fail.", + "description": "Set this option to false to continue downloading data set members if one or more fail.", "name": "fail-fast", "type": "boolean", }, @@ -72,7 +72,7 @@ The maximum number of TSO address spaces have been created. When you specify 0, "name": "max-concurrent-requests", "numericValueRange": Array [ 0, - 99999, + 100, ], "type": "number", }, @@ -81,7 +81,7 @@ The maximum number of TSO address spaces have been created. When you specify 0, "po", ], "defaultValue": false, - "description": "Specifies if the automatically generated directories and files use the original letter case", + "description": "Specifies if the automatically generated directories and files use the original letter case.", "name": "preserve-original-letter-case", "type": "boolean", }, diff --git a/packages/cli/__tests__/zosfiles/__unit__/download/uss/UssFile.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/download/uss/UssFile.handler.unit.test.ts index e99676bec2..55afdf6edf 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/download/uss/UssFile.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/download/uss/UssFile.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Download } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Download uss file handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/download/ussdir/UssDir.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/download/ussdir/UssDir.handler.unit.test.ts index 64857d28ba..9619831883 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/download/ussdir/UssDir.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/download/ussdir/UssDir.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Download, IDownloadOptions, IUSSListOptions } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; const defaultListObj: IUSSListOptions = { name: "*", diff --git a/packages/cli/__tests__/zosfiles/__unit__/download/ussdir/__snapshots__/UssDir.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/download/ussdir/__snapshots__/UssDir.definition.unit.test.ts.snap index b1820ecad0..62d8a6fd67 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/download/ussdir/__snapshots__/UssDir.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/download/ussdir/__snapshots__/UssDir.definition.unit.test.ts.snap @@ -10,7 +10,7 @@ Array [ "binary", "record", ], - "description": "Path of an attributes file to control how files are downloaded", + "description": "Path of an attributes file to control how files are downloaded.", "name": "attributes", "type": "existingLocalFile", }, @@ -66,7 +66,7 @@ Array [ "aliases": Array [ "ih", ], - "description": "Include hidden files and folders that have names beginning with a dot", + "description": "Include hidden files and folders that have names beginning with a dot.", "name": "include-hidden", "type": "boolean", }, @@ -80,7 +80,7 @@ The maximum number of TSO address spaces have been created. When you specify 0, "name": "max-concurrent-requests", "numericValueRange": Array [ 0, - 99999, + 100, ], "type": "number", }, @@ -106,7 +106,7 @@ The maximum number of TSO address spaces have been created. When you specify 0, "aliases": Array [ "ow", ], - "description": "Overwrite files that already exist in your local environment", + "description": "Overwrite files that already exist in your local environment.", "name": "overwrite", "type": "boolean", }, diff --git a/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.handler.unit.test.ts index e60b145612..7a30a79836 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.handler.unit.test.ts @@ -15,7 +15,7 @@ import {ILocalFile, import { mockHandlerParameters } from "@zowe/cli-test-utils"; import { EditDefinition } from "../../../../src/zosfiles/edit/Edit.definition"; import EditHandler from "../../../../src/zosfiles/edit/Edit.handler"; -import { UNIT_TEST_PROFILES_ZOSMF, UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../__tests__/__src__/TestConstants"; import stripAnsi = require("strip-ansi"); describe("Files Edit Group Handler", () => { @@ -27,8 +27,7 @@ describe("Files Edit Group Handler", () => { const commandParameters: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-files", "edit", "ds"], - definition: EditDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: EditDefinition }); const localFile: ILocalFile = { diff --git a/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.utils.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.utils.unit.test.ts index 66370a903d..a68cb87fa2 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.utils.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/edit/Edit.utils.unit.test.ts @@ -11,7 +11,7 @@ import { mockHandlerParameters } from "@zowe/cli-test-utils"; import { AbstractSession, CliUtils, GuiResult, IHandlerParameters, ImperativeError, ProcessUtils } from "@zowe/imperative"; -import { UNIT_TEST_ZOSMF_PROF_OPTS, UNIT_TEST_PROFILES_ZOSMF } from "../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../__tests__/__src__/TestConstants"; import { EditDefinition } from "../../../../src/zosfiles/edit/Edit.definition"; import { EditUtilities, ILocalFile, Prompt } from "../../../../src/zosfiles/edit/Edit.utils"; import { cloneDeep } from "lodash"; @@ -26,15 +26,13 @@ describe("Files Edit Utilities", () => { const commandParametersDs: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-files", "edit", "ds"], - definition: EditDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: EditDefinition }); const commandParametersUss: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-files", "edit", "uss"], - definition: EditDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: EditDefinition }); commandParametersDs.arguments["dataSetName"] = commandParametersUss.arguments["file"] = 'fake'; @@ -371,7 +369,7 @@ describe("Files Edit Utilities", () => { //TEST CONFIRMATION await EditUtilities.fileComparison(REAL_SESSION, commandParametersDs, localFileDS); - expect(getFile2DsSpy).toBeCalledWith(undefined, expect.anything(), expect.objectContaining({ + expect(getFile2DsSpy).toHaveBeenCalledWith(undefined, expect.anything(), expect.objectContaining({ "browserView": true })); }); @@ -428,12 +426,12 @@ describe("Files Edit Utilities", () => { it("should open in editor if one specified, otherwise skip to prompting", async () => { const openInEditorSpy = jest.spyOn(ProcessUtils, "openInEditor").mockImplementation(jest.fn()); await EditUtilities.makeEdits(localFile, 'editorPath'); - expect(openInEditorSpy).toBeCalledTimes(1); + expect(openInEditorSpy).toHaveBeenCalledTimes(1); }); it("should skip to prompting if no supplied editor", async () => { const promptUserSpy = jest.spyOn(EditUtilities, "promptUser"); await EditUtilities.makeEdits(localFile, 'editorPath'); - expect(promptUserSpy).toBeCalledTimes(1); + expect(promptUserSpy).toHaveBeenCalledTimes(1); }); }); describe("uploadEdits()", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/invoke/amsFile/AmsFile.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/invoke/amsFile/AmsFile.handler.unit.test.ts index 5d84602ce3..f915990226 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/invoke/amsFile/AmsFile.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/invoke/amsFile/AmsFile.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Invoke, IZosFilesOptions } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Invoke AMS files handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/invoke/amsStatements/AmsStatements.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/invoke/amsStatements/AmsStatements.handler.unit.test.ts index df59cc5cff..4b3773a186 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/invoke/amsStatements/AmsStatements.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/invoke/amsStatements/AmsStatements.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Invoke } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Invoke AMS statements handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/list/am/AllMembers.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/list/am/AllMembers.handler.unit.test.ts index 55871bc2ab..cf11e3a249 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/list/am/AllMembers.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/list/am/AllMembers.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { List } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { IHandlerParameters } from "@zowe/imperative"; describe("List AllMembers handler", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/list/ds/Dataset.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/list/ds/Dataset.handler.unit.test.ts index e87a31e6d2..75f217a634 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/list/ds/Dataset.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/list/ds/Dataset.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { List } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("List Dataset handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/list/fs/Fs.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/list/fs/Fs.handler.unit.test.ts index 53e27e5c44..a052f68a63 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/list/fs/Fs.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/list/fs/Fs.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { List } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("fs handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/list/uss/Uss.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/list/uss/Uss.handler.unit.test.ts index 20ab8f4c07..54f0eba9de 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/list/uss/Uss.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/list/uss/Uss.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { List } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("USS file handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/mount/fs/fs.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/mount/fs/fs.handler.unit.test.ts index 5340676739..2a4fdee14a 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/mount/fs/fs.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/mount/fs/fs.handler.unit.test.ts @@ -11,7 +11,7 @@ import { Mount } from "@zowe/zos-files-for-zowe-sdk"; import { ImperativeError } from "@zowe/imperative"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; const message: string = "Dummy error message"; diff --git a/packages/cli/__tests__/zosfiles/__unit__/search/Search.definition.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/search/Search.definition.unit.test.ts new file mode 100644 index 0000000000..2de665e572 --- /dev/null +++ b/packages/cli/__tests__/zosfiles/__unit__/search/Search.definition.unit.test.ts @@ -0,0 +1,27 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ICommandDefinition } from "@zowe/imperative"; + +describe("zos-files search group definition", () => { + it ("should not have changed", () => { + const definition: ICommandDefinition = require("../../../../src/zosfiles/search/Search.definition").SearchDefinition; + + expect(definition).toBeDefined(); + + // Should not contain options nor examples since this is a group + expect(definition.options).toBeUndefined(); + expect(definition.examples).toBeUndefined(); + + // Should have children since this is a group + expect(definition.children).toBeDefined(); + }); +}); diff --git a/packages/cli/__tests__/zosfiles/__unit__/search/ds/Datasets.definition.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/search/ds/Datasets.definition.unit.test.ts new file mode 100644 index 0000000000..60ca2372f0 --- /dev/null +++ b/packages/cli/__tests__/zosfiles/__unit__/search/ds/Datasets.definition.unit.test.ts @@ -0,0 +1,37 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ICommandDefinition } from "@zowe/imperative"; + +describe("zos-files search ds command definition", () => { + it ("should not have changed", () => { + const definition: ICommandDefinition = require("../../../../../src/zosfiles/search/ds/DataSets.definition").DataSetsDefinition; + + expect(definition).toBeDefined(); + + // Should not contain children since this is a command + expect(definition.children).toBeUndefined(); + + // Should require a zosmf profile + expect(definition.profile.optional).toEqual(["zosmf"]); + + // Should contain two positionals + expect(definition.positionals.length).toEqual(2); + + // The positionals should be required + expect(definition.positionals[0].required).toBeTruthy(); + expect(definition.positionals[1].required).toBeTruthy(); + + // Should not change + expect(definition.options).toMatchSnapshot(); + expect(definition.examples).toMatchSnapshot(); + }); +}); diff --git a/packages/cli/__tests__/zosfiles/__unit__/search/ds/Datasets.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/search/ds/Datasets.handler.unit.test.ts new file mode 100644 index 0000000000..d3ed3f18c0 --- /dev/null +++ b/packages/cli/__tests__/zosfiles/__unit__/search/ds/Datasets.handler.unit.test.ts @@ -0,0 +1,118 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + + +import { Search } from "@zowe/zos-files-for-zowe-sdk"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; +import { TaskStage } from "@zowe/imperative"; + +describe("Search Datasets handler", () => { + describe("process method", () => { + it("should search a data set if requested", async () => { + // Require the handler and create a new instance + const handlerReq = require("../../../../../src/zosfiles/search/ds/DataSets.handler"); + const handler = new handlerReq.default(); + const pattern = "TEST*"; + const searchString = "test"; + + // Vars populated by the mocked function + let apiMessage = ""; + let jsonObj; + let logMessage = ""; + let fakeSession = null; + + // Mock the submit JCL function + Search.dataSets = jest.fn(async (session) => { + fakeSession = session; + return { + success: true, + commandResponse: "Found \"test\" in 2 data sets and PDS members", + apiResponse: [ + { + dsname: "TEST1.DS", + memname: "TESTMEM", + matchList: [ + { + line: 1, + column: 1, + contents: "TEST CONTENTS" + } + ] + }, + { + dsname: "TEST2.DS", + memname: undefined, + matchList: [ + { + line: 1, + column: 1, + contents: "TEST CONTENTS" + } + ] + } + ] + }; + }); + + // Invoke the handler with a full set of mocked arguments and response functions + await handler.process({ + arguments: { + $0: "fake", + _: ["fake"], + pattern, + searchString, + ...UNIT_TEST_ZOSMF_PROF_OPTS + }, + response: { + data: { + setMessage: jest.fn((setMsgArgs) => { + apiMessage = setMsgArgs; + }), + setObj: jest.fn((setObjArgs) => { + jsonObj = setObjArgs; + }) + }, + console: { + log: jest.fn((logArgs) => { + logMessage += "\n" + logArgs; + }) + }, + progress: { + startBar: jest.fn((parms) => { + // do nothing + }), + endBar: jest.fn(() => { + // do nothing + }) + } + } + } as any); + + expect(Search.dataSets).toHaveBeenCalledTimes(1); + expect(Search.dataSets).toHaveBeenCalledWith(fakeSession, { + pattern, + searchString, + caseSensitive: undefined, + mainframeSearch: undefined, + maxConcurrentRequests: undefined, + timeout: undefined, + progressTask: { + percentComplete: 0, + statusMessage: "Starting search...", + stageName: TaskStage.NOT_STARTED + } + }); + expect(jsonObj).toMatchSnapshot(); + expect(apiMessage).toMatchSnapshot(); + expect(logMessage).toMatchSnapshot(); + }); + }); +}); diff --git a/packages/cli/__tests__/zosfiles/__unit__/search/ds/__snapshots__/Datasets.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/search/ds/__snapshots__/Datasets.definition.unit.test.ts.snap new file mode 100644 index 0000000000..4e1984d282 --- /dev/null +++ b/packages/cli/__tests__/zosfiles/__unit__/search/ds/__snapshots__/Datasets.definition.unit.test.ts.snap @@ -0,0 +1,66 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`zos-files search ds command definition should not have changed 1`] = ` +Array [ + Object { + "aliases": Array [ + "cs", + ], + "defaultValue": false, + "description": "The search should be case sensitive", + "name": "case-sensitive", + "type": "boolean", + }, + Object { + "aliases": Array [ + "ms", + ], + "defaultValue": false, + "description": "Perform a preliminary search on the mainframe, reducing network traffic. However, this option does not work with data sets that contain binary data. This option should be omitted if any data sets may be in binary format. Failure to do so may result in an incomplete set of search results.", + "name": "mainframe-search", + "type": "boolean", + }, + Object { + "aliases": Array [ + "mcr", + ], + "defaultValue": 1, + "description": "Specifies the maximum number of concurrent z/OSMF REST API requests to search files. Increasing the value results in faster searches. However, increasing the value increases resource consumption on z/OS and can be prone to errors caused by making too many concurrent requests.", + "name": "max-concurrent-requests", + "numericValueRange": Array [ + 1, + 100, + ], + "type": "number", + }, + Object { + "aliases": Array [ + "to", + ], + "description": "The number of seconds to search before timing out", + "name": "timeout", + "type": "number", + }, +] +`; + +exports[`zos-files search ds command definition should not have changed 2`] = ` +Array [ + Object { + "description": "Search all of IBMUSER's, data sets for 'ZOWE'", + "options": "'IBMUSER.*' 'ZOWE'", + }, + Object { + "description": "Search all of IBMUSER's, data sets for 'ZOWE' in uppercase only", + "options": "'IBMUSER.*' 'ZOWE' --case-sensitive", + }, + Object { + "description": "Search all of IBMUSER's, data sets for 'ZOWE', and time out in 1 minute", + "options": "'IBMUSER.*' 'ZOWE' --timeout 60", + }, + Object { + "description": "Search all of IBMUSER's, data sets for 'ZOWE', and perform 8 parallel tasks", + "options": "'IBMUSER.*' 'ZOWE' --max-concurrent-requests 8", + }, +] +`; diff --git a/packages/cli/__tests__/zosfiles/__unit__/search/ds/__snapshots__/Datasets.handler.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/search/ds/__snapshots__/Datasets.handler.unit.test.ts.snap new file mode 100644 index 0000000000..8add350f82 --- /dev/null +++ b/packages/cli/__tests__/zosfiles/__unit__/search/ds/__snapshots__/Datasets.handler.unit.test.ts.snap @@ -0,0 +1,39 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Search Datasets handler process method should search a data set if requested 1`] = ` +Object { + "apiResponse": Array [ + Object { + "dsname": "TEST1.DS", + "matchList": Array [ + Object { + "column": 1, + "contents": "TEST CONTENTS", + "line": 1, + }, + ], + "memname": "TESTMEM", + }, + Object { + "dsname": "TEST2.DS", + "matchList": Array [ + Object { + "column": 1, + "contents": "TEST CONTENTS", + "line": 1, + }, + ], + "memname": undefined, + }, + ], + "commandResponse": "Found \\"test\\" in 2 data sets and PDS members", + "success": true, +} +`; + +exports[`Search Datasets handler process method should search a data set if requested 2`] = `""`; + +exports[`Search Datasets handler process method should search a data set if requested 3`] = ` +" +Found \\"test\\" in 2 data sets and PDS members" +`; diff --git a/packages/cli/__tests__/zosfiles/__unit__/upload/dtp/DirToPds.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/upload/dtp/DirToPds.handler.unit.test.ts index aba9173262..a544f56b6c 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/upload/dtp/DirToPds.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/upload/dtp/DirToPds.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Upload } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Upload dir-to-pds handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/upload/dtu/DirToUSS.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/upload/dtu/DirToUSS.handler.unit.test.ts index de04c2c0e7..f1965a7d8d 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/upload/dtu/DirToUSS.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/upload/dtu/DirToUSS.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Upload, ZosFilesAttributes } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import * as fs from "fs"; describe("Upload dir-to-uss handler", () => { @@ -113,7 +113,7 @@ describe("Upload dir-to-uss handler", () => { // eslint-disable-next-line jest/expect-expect it("should give an error if --attributes specifies a non-existent file", async () => { jest.spyOn(fs, "existsSync").mockReturnValueOnce(false); - const params = Object.assign({}, ...[DEFAULT_PARAMETERS]); + const params = Object.assign({arguments: {attributes: undefined}}, ...[DEFAULT_PARAMETERS]); params.arguments.attributes = "non-existent-file"; await testHandlerGivesExpectedErrorWithParams("Attributes file non-existent-file does not exist", params); @@ -125,7 +125,7 @@ describe("Upload dir-to-uss handler", () => { jest.spyOn(fs, "readFileSync").mockImplementationOnce(() => { throw new Error("File not found"); }); - const params = Object.assign({}, ...[DEFAULT_PARAMETERS]); + const params = Object.assign({arguments: {attributes: undefined}}, ...[DEFAULT_PARAMETERS]); params.arguments.attributes = "dodgy file"; await testHandlerGivesExpectedErrorWithParams("Could not read attributes file dodgy file: File not found", params); @@ -142,7 +142,7 @@ describe("Upload dir-to-uss handler", () => { } }); - const params = Object.assign({}, ...[DEFAULT_PARAMETERS]); + const params = Object.assign({arguments: {attributes: undefined}}, ...[DEFAULT_PARAMETERS]); params.arguments.attributes = "real file"; await testHandlerWorksWithParameters(params); diff --git a/packages/cli/__tests__/zosfiles/__unit__/upload/dtu/__snapshots__/DirToUSS.definition.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/upload/dtu/__snapshots__/DirToUSS.definition.unit.test.ts.snap index dbefb890e9..d39c1604e9 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/upload/dtu/__snapshots__/DirToUSS.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/upload/dtu/__snapshots__/DirToUSS.definition.unit.test.ts.snap @@ -47,7 +47,7 @@ Array [ "conflictsWith": Array [ "ascii-files, binary-files", ], - "description": "Path of an attributes file to control how files are uploaded", + "description": "Path of an attributes file to control how files are uploaded.", "name": "attributes", "type": "string", }, @@ -61,7 +61,7 @@ The maximum number of TSO address spaces have been created. When you specify 0, "name": "max-concurrent-requests", "numericValueRange": Array [ 0, - 99999, + 100, ], "type": "number", }, @@ -69,7 +69,7 @@ The maximum number of TSO address spaces have been created. When you specify 0, "aliases": Array [ "ih", ], - "description": "Include hidden files and folders that have names beginning with a dot", + "description": "Include hidden files and folders that have names beginning with a dot.", "name": "include-hidden", "type": "boolean", }, diff --git a/packages/cli/__tests__/zosfiles/__unit__/upload/ftds/FileToDataSet.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/upload/ftds/FileToDataSet.handler.unit.test.ts index cddbc54373..c71ada1d52 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/upload/ftds/FileToDataSet.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/upload/ftds/FileToDataSet.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Upload } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Upload file-to-data-set handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/upload/ftu/FileToUSS.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/upload/ftu/FileToUSS.handler.unit.test.ts index 9e027cd02c..c4eedd2bd4 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/upload/ftu/FileToUSS.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/upload/ftu/FileToUSS.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Upload } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Upload file-to-uss handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/upload/stds/StdinToDataSet.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/upload/stds/StdinToDataSet.handler.unit.test.ts index 51b8e92c49..fbd3bdd65f 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/upload/stds/StdinToDataSet.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/upload/stds/StdinToDataSet.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Upload } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("Upload stdin-to-data-set handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/view/ds/Dataset.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/view/ds/Dataset.handler.unit.test.ts index 828246841e..a2b544a611 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/view/ds/Dataset.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/view/ds/Dataset.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Get } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("View data set handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosfiles/__unit__/view/uss/USSFiles.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/view/uss/USSFiles.handler.unit.test.ts index cdb40f7868..a3069f959c 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/view/uss/USSFiles.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/view/uss/USSFiles.handler.unit.test.ts @@ -10,7 +10,7 @@ */ import { Get } from "@zowe/zos-files-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; describe("View USS file handler", () => { describe("process method", () => { diff --git a/packages/cli/__tests__/zosjobs/__integration__/__snapshots__/cli.zos-jobs.integration.test.ts.snap b/packages/cli/__tests__/zosjobs/__integration__/__snapshots__/cli.zos-jobs.integration.test.ts.snap index cd4e2e0c66..25421d92c3 100644 --- a/packages/cli/__tests__/zosjobs/__integration__/__snapshots__/cli.zos-jobs.integration.test.ts.snap +++ b/packages/cli/__tests__/zosjobs/__integration__/__snapshots__/cli.zos-jobs.integration.test.ts.snap @@ -17,13 +17,14 @@ exports[`zos-jobs command should display the help 1`] = ` GROUPS ------ - cancel | can Cancel a z/OS job - delete | del Delete a z/OS job or jobs - download | dl Download job output - list | ls List jobs and spool files - modify | mod Modify a z/OS job - submit | sub Submit a z/OS job - view | vw View details of a z/OS job + cancel | can Cancel a z/OS job + delete | del Delete a z/OS job or jobs + download | dl Download job output + list | ls List jobs and spool files + modify | mod Modify a z/OS job + search | sea Search the spool output of a z/OS job + submit | sub Submit a z/OS job + view | vw View details of a z/OS job GLOBAL OPTIONS -------------- @@ -48,8 +49,8 @@ exports[`zos-jobs command should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: zos-jobs.\\", - \\"stdout\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Manage z/OS jobs.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs \\\\n\\\\n Where is one of the following:\\\\n\\\\n GROUPS\\\\n ------\\\\n\\\\n cancel | can Cancel a z/OS job \\\\n delete | del Delete a z/OS job or jobs \\\\n download | dl Download job output \\\\n list | ls List jobs and spool files \\\\n modify | mod Modify a z/OS job \\\\n submit | sub Submit a z/OS job \\\\n view | vw View details of a z/OS job\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Manage z/OS jobs.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs \\\\n\\\\n Where is one of the following:\\\\n\\\\n GROUPS\\\\n ------\\\\n\\\\n cancel | can Cancel a z/OS job \\\\n delete | del Delete a z/OS job or jobs \\\\n download | dl Download job output \\\\n list | ls List jobs and spool files \\\\n modify | mod Modify a z/OS job \\\\n search | sea Search the spool output of a z/OS job\\\\n submit | sub Submit a z/OS job \\\\n view | vw View details of a z/OS job \\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Manage z/OS jobs.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs \\\\n\\\\n Where is one of the following:\\\\n\\\\n GROUPS\\\\n ------\\\\n\\\\n cancel | can Cancel a z/OS job \\\\n delete | del Delete a z/OS job or jobs \\\\n download | dl Download job output \\\\n list | ls List jobs and spool files \\\\n modify | mod Modify a z/OS job \\\\n submit | sub Submit a z/OS job \\\\n view | vw View details of a z/OS job\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" + \\"data\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Manage z/OS jobs.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs \\\\n\\\\n Where is one of the following:\\\\n\\\\n GROUPS\\\\n ------\\\\n\\\\n cancel | can Cancel a z/OS job \\\\n delete | del Delete a z/OS job or jobs \\\\n download | dl Download job output \\\\n list | ls List jobs and spool files \\\\n modify | mod Modify a z/OS job \\\\n search | sea Search the spool output of a z/OS job\\\\n submit | sub Submit a z/OS job \\\\n view | vw View details of a z/OS job \\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosjobs/__integration__/cancel/__snapshots__/cli.zos-jobs.cancel.job.integration.test.ts.snap b/packages/cli/__tests__/zosjobs/__integration__/cancel/__snapshots__/cli.zos-jobs.cancel.job.integration.test.ts.snap index a57febf0df..2340d86174 100644 --- a/packages/cli/__tests__/zosjobs/__integration__/cancel/__snapshots__/cli.zos-jobs.cancel.job.integration.test.ts.snap +++ b/packages/cli/__tests__/zosjobs/__integration__/cancel/__snapshots__/cli.zos-jobs.cancel.job.integration.test.ts.snap @@ -28,7 +28,7 @@ exports[`zos-jobs cancel job command should display the help 1`] = ` DESCRIPTION ----------- - Cancel a single job by job ID + Cancel a single job by job ID. USAGE ----- @@ -50,7 +50,7 @@ exports[`zos-jobs cancel job command should display the help 1`] = ` --modify-version (string) Using this option to set X-IBM-Job-Modify-Version to \\"1.0\\" will make the delete - job API aynchronous. Otherwise, it will be synchronous by default. + job API asynchronous. Otherwise, it will be synchronous by default. Default value: 2.0 @@ -159,8 +159,8 @@ exports[`zos-jobs cancel job command should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: job.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n job\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Cancel a single job by job ID\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs cancel job [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n jobid\\\\t\\\\t (string)\\\\n\\\\n The job ID (e.g. JOB00123) of the job. Job ID is a unique identifier for z/OS\\\\n batch jobs -- no two jobs on one system can have the same ID. Note: z/OS allows\\\\n you to abbreviate the job ID if desired. You can use, for example \\\\\\"J123\\\\\\".\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --modify-version (string)\\\\n\\\\n Using this option to set X-IBM-Job-Modify-Version to \\\\\\"1.0\\\\\\" will make the delete\\\\n job API aynchronous. Otherwise, it will be synchronous by default.\\\\n\\\\n Default value: 2.0\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Cancel job with job ID JOB03456:\\\\n\\\\n $ zowe zos-jobs cancel job JOB03456\\\\n\\\\n - Cancel job with job ID JOB03456 synchronously:\\\\n\\\\n $ zowe zos-jobs cancel job JOB03456 --modify-version \\\\\\"2.0\\\\\\"\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n job\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Cancel a single job by job ID.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs cancel job [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n jobid\\\\t\\\\t (string)\\\\n\\\\n The job ID (e.g. JOB00123) of the job. Job ID is a unique identifier for z/OS\\\\n batch jobs -- no two jobs on one system can have the same ID. Note: z/OS allows\\\\n you to abbreviate the job ID if desired. You can use, for example \\\\\\"J123\\\\\\".\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --modify-version (string)\\\\n\\\\n Using this option to set X-IBM-Job-Modify-Version to \\\\\\"1.0\\\\\\" will make the delete\\\\n job API asynchronous. Otherwise, it will be synchronous by default.\\\\n\\\\n Default value: 2.0\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Cancel job with job ID JOB03456:\\\\n\\\\n $ zowe zos-jobs cancel job JOB03456\\\\n\\\\n - Cancel job with job ID JOB03456 synchronously:\\\\n\\\\n $ zowe zos-jobs cancel job JOB03456 --modify-version \\\\\\"2.0\\\\\\"\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n job\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Cancel a single job by job ID\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs cancel job [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n jobid\\\\t\\\\t (string)\\\\n\\\\n The job ID (e.g. JOB00123) of the job. Job ID is a unique identifier for z/OS\\\\n batch jobs -- no two jobs on one system can have the same ID. Note: z/OS allows\\\\n you to abbreviate the job ID if desired. You can use, for example \\\\\\"J123\\\\\\".\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --modify-version (string)\\\\n\\\\n Using this option to set X-IBM-Job-Modify-Version to \\\\\\"1.0\\\\\\" will make the delete\\\\n job API aynchronous. Otherwise, it will be synchronous by default.\\\\n\\\\n Default value: 2.0\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Cancel job with job ID JOB03456:\\\\n\\\\n $ zowe zos-jobs cancel job JOB03456\\\\n\\\\n - Cancel job with job ID JOB03456 synchronously:\\\\n\\\\n $ zowe zos-jobs cancel job JOB03456 --modify-version \\\\\\"2.0\\\\\\"\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n job\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Cancel a single job by job ID.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs cancel job [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n jobid\\\\t\\\\t (string)\\\\n\\\\n The job ID (e.g. JOB00123) of the job. Job ID is a unique identifier for z/OS\\\\n batch jobs -- no two jobs on one system can have the same ID. Note: z/OS allows\\\\n you to abbreviate the job ID if desired. You can use, for example \\\\\\"J123\\\\\\".\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --modify-version (string)\\\\n\\\\n Using this option to set X-IBM-Job-Modify-Version to \\\\\\"1.0\\\\\\" will make the delete\\\\n job API asynchronous. Otherwise, it will be synchronous by default.\\\\n\\\\n Default value: 2.0\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Cancel job with job ID JOB03456:\\\\n\\\\n $ zowe zos-jobs cancel job JOB03456\\\\n\\\\n - Cancel job with job ID JOB03456 synchronously:\\\\n\\\\n $ zowe zos-jobs cancel job JOB03456 --modify-version \\\\\\"2.0\\\\\\"\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosjobs/__integration__/delete/__snapshots__/cli.zos-jobs.delete.job.integration.test.ts.snap b/packages/cli/__tests__/zosjobs/__integration__/delete/__snapshots__/cli.zos-jobs.delete.job.integration.test.ts.snap index 78788c1c6e..1073ac991b 100644 --- a/packages/cli/__tests__/zosjobs/__integration__/delete/__snapshots__/cli.zos-jobs.delete.job.integration.test.ts.snap +++ b/packages/cli/__tests__/zosjobs/__integration__/delete/__snapshots__/cli.zos-jobs.delete.job.integration.test.ts.snap @@ -28,7 +28,7 @@ exports[`zos-jobs delete job command should display the help 1`] = ` DESCRIPTION ----------- - Delete a single job by job ID + Delete a single job by job ID. USAGE ----- @@ -50,7 +50,7 @@ exports[`zos-jobs delete job command should display the help 1`] = ` --modify-version (string) Using this option to set X-IBM-Job-Modify-Version to \\"1.0\\" will make the delete - job API aynchronous. Otherwise, it will be synchronous by default. + job API asynchronous. Otherwise, it will be synchronous by default. Default value: 2.0 @@ -159,8 +159,8 @@ exports[`zos-jobs delete job command should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: job.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n job\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete a single job by job ID\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs delete job [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n jobid\\\\t\\\\t (string)\\\\n\\\\n The job ID (e.g. JOB00123) of the job. Job ID is a unique identifier for z/OS\\\\n batch jobs -- no two jobs on one system can have the same ID. Note: z/OS allows\\\\n you to abbreviate the job ID if desired. You can use, for example \\\\\\"J123\\\\\\".\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --modify-version (string)\\\\n\\\\n Using this option to set X-IBM-Job-Modify-Version to \\\\\\"1.0\\\\\\" will make the delete\\\\n job API aynchronous. Otherwise, it will be synchronous by default.\\\\n\\\\n Default value: 2.0\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete job with job ID JOB03456:\\\\n\\\\n $ zowe zos-jobs delete job JOB03456\\\\n\\\\n - Delete job with job ID JOB03456 synchronously:\\\\n\\\\n $ zowe zos-jobs delete job JOB03456 --modify-version \\\\\\"2.0\\\\\\"\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n job\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete a single job by job ID.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs delete job [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n jobid\\\\t\\\\t (string)\\\\n\\\\n The job ID (e.g. JOB00123) of the job. Job ID is a unique identifier for z/OS\\\\n batch jobs -- no two jobs on one system can have the same ID. Note: z/OS allows\\\\n you to abbreviate the job ID if desired. You can use, for example \\\\\\"J123\\\\\\".\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --modify-version (string)\\\\n\\\\n Using this option to set X-IBM-Job-Modify-Version to \\\\\\"1.0\\\\\\" will make the delete\\\\n job API asynchronous. Otherwise, it will be synchronous by default.\\\\n\\\\n Default value: 2.0\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete job with job ID JOB03456:\\\\n\\\\n $ zowe zos-jobs delete job JOB03456\\\\n\\\\n - Delete job with job ID JOB03456 synchronously:\\\\n\\\\n $ zowe zos-jobs delete job JOB03456 --modify-version \\\\\\"2.0\\\\\\"\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n job\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete a single job by job ID\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs delete job [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n jobid\\\\t\\\\t (string)\\\\n\\\\n The job ID (e.g. JOB00123) of the job. Job ID is a unique identifier for z/OS\\\\n batch jobs -- no two jobs on one system can have the same ID. Note: z/OS allows\\\\n you to abbreviate the job ID if desired. You can use, for example \\\\\\"J123\\\\\\".\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --modify-version (string)\\\\n\\\\n Using this option to set X-IBM-Job-Modify-Version to \\\\\\"1.0\\\\\\" will make the delete\\\\n job API aynchronous. Otherwise, it will be synchronous by default.\\\\n\\\\n Default value: 2.0\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete job with job ID JOB03456:\\\\n\\\\n $ zowe zos-jobs delete job JOB03456\\\\n\\\\n - Delete job with job ID JOB03456 synchronously:\\\\n\\\\n $ zowe zos-jobs delete job JOB03456 --modify-version \\\\\\"2.0\\\\\\"\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n job\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete a single job by job ID.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs delete job [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n jobid\\\\t\\\\t (string)\\\\n\\\\n The job ID (e.g. JOB00123) of the job. Job ID is a unique identifier for z/OS\\\\n batch jobs -- no two jobs on one system can have the same ID. Note: z/OS allows\\\\n you to abbreviate the job ID if desired. You can use, for example \\\\\\"J123\\\\\\".\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --modify-version (string)\\\\n\\\\n Using this option to set X-IBM-Job-Modify-Version to \\\\\\"1.0\\\\\\" will make the delete\\\\n job API asynchronous. Otherwise, it will be synchronous by default.\\\\n\\\\n Default value: 2.0\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete job with job ID JOB03456:\\\\n\\\\n $ zowe zos-jobs delete job JOB03456\\\\n\\\\n - Delete job with job ID JOB03456 synchronously:\\\\n\\\\n $ zowe zos-jobs delete job JOB03456 --modify-version \\\\\\"2.0\\\\\\"\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosjobs/__integration__/delete/__snapshots__/cli.zos-jobs.delete.old-jobs.integration.test.ts.snap b/packages/cli/__tests__/zosjobs/__integration__/delete/__snapshots__/cli.zos-jobs.delete.old-jobs.integration.test.ts.snap index a136e6d03e..2f99957640 100644 --- a/packages/cli/__tests__/zosjobs/__integration__/delete/__snapshots__/cli.zos-jobs.delete.old-jobs.integration.test.ts.snap +++ b/packages/cli/__tests__/zosjobs/__integration__/delete/__snapshots__/cli.zos-jobs.delete.old-jobs.integration.test.ts.snap @@ -63,7 +63,7 @@ exports[`zos-jobs delete old-jobs command should display the help 1`] = ` --modify-version (string) Using this option to set X-IBM-Job-Modify-Version to \\"1.0\\" will make the delete - job API aynchronous. Otherwise, it will be synchronous by default. + job API asynchronous. Otherwise, it will be synchronous by default. Default value: 2.0 @@ -169,8 +169,8 @@ exports[`zos-jobs delete old-jobs command should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: old-jobs.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n old-jobs | oj\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete (purge) jobs in OUTPUT status. Defaults to deleting all jobs owned by\\\\n your user ID that are in output status.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs delete old-jobs [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --prefix | -p (string)\\\\n\\\\n Only delete jobs with job names that match this prefix. Defaults to deleting all\\\\n jobs owned by your user ID that are in output status.\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to delete\\\\n jobs. Increasing the value makes the command run faster. However, increasing the\\\\n value increases resource consumption on z/OS and can be prone to errors caused\\\\n by making too many concurrent requests. When you specify 0, Zowe CLI attempts to\\\\n delete all jobs at once without a maximum number of concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --modify-version (string)\\\\n\\\\n Using this option to set X-IBM-Job-Modify-Version to \\\\\\"1.0\\\\\\" will make the delete\\\\n job API aynchronous. Otherwise, it will be synchronous by default.\\\\n\\\\n Default value: 2.0\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete all of your jobs in output status with a job name\\\\n starting with \\\\\\"ibmuser\\\\\\":\\\\n\\\\n $ zowe zos-jobs delete old-jobs -p \\\\\\"ibmuser*\\\\\\"\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n old-jobs | oj\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete (purge) jobs in OUTPUT status. Defaults to deleting all jobs owned by\\\\n your user ID that are in output status.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs delete old-jobs [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --prefix | -p (string)\\\\n\\\\n Only delete jobs with job names that match this prefix. Defaults to deleting all\\\\n jobs owned by your user ID that are in output status.\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to delete\\\\n jobs. Increasing the value makes the command run faster. However, increasing the\\\\n value increases resource consumption on z/OS and can be prone to errors caused\\\\n by making too many concurrent requests. When you specify 0, Zowe CLI attempts to\\\\n delete all jobs at once without a maximum number of concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --modify-version (string)\\\\n\\\\n Using this option to set X-IBM-Job-Modify-Version to \\\\\\"1.0\\\\\\" will make the delete\\\\n job API asynchronous. Otherwise, it will be synchronous by default.\\\\n\\\\n Default value: 2.0\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete all of your jobs in output status with a job name\\\\n starting with \\\\\\"ibmuser\\\\\\":\\\\n\\\\n $ zowe zos-jobs delete old-jobs -p \\\\\\"ibmuser*\\\\\\"\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n old-jobs | oj\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete (purge) jobs in OUTPUT status. Defaults to deleting all jobs owned by\\\\n your user ID that are in output status.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs delete old-jobs [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --prefix | -p (string)\\\\n\\\\n Only delete jobs with job names that match this prefix. Defaults to deleting all\\\\n jobs owned by your user ID that are in output status.\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to delete\\\\n jobs. Increasing the value makes the command run faster. However, increasing the\\\\n value increases resource consumption on z/OS and can be prone to errors caused\\\\n by making too many concurrent requests. When you specify 0, Zowe CLI attempts to\\\\n delete all jobs at once without a maximum number of concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --modify-version (string)\\\\n\\\\n Using this option to set X-IBM-Job-Modify-Version to \\\\\\"1.0\\\\\\" will make the delete\\\\n job API aynchronous. Otherwise, it will be synchronous by default.\\\\n\\\\n Default value: 2.0\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete all of your jobs in output status with a job name\\\\n starting with \\\\\\"ibmuser\\\\\\":\\\\n\\\\n $ zowe zos-jobs delete old-jobs -p \\\\\\"ibmuser*\\\\\\"\\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n old-jobs | oj\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Delete (purge) jobs in OUTPUT status. Defaults to deleting all jobs owned by\\\\n your user ID that are in output status.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs delete old-jobs [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --prefix | -p (string)\\\\n\\\\n Only delete jobs with job names that match this prefix. Defaults to deleting all\\\\n jobs owned by your user ID that are in output status.\\\\n\\\\n --max-concurrent-requests | --mcr (number)\\\\n\\\\n Specifies the maximum number of concurrent z/OSMF REST API requests to delete\\\\n jobs. Increasing the value makes the command run faster. However, increasing the\\\\n value increases resource consumption on z/OS and can be prone to errors caused\\\\n by making too many concurrent requests. When you specify 0, Zowe CLI attempts to\\\\n delete all jobs at once without a maximum number of concurrent requests.\\\\n\\\\n Default value: 1\\\\n\\\\n --modify-version (string)\\\\n\\\\n Using this option to set X-IBM-Job-Modify-Version to \\\\\\"1.0\\\\\\" will make the delete\\\\n job API asynchronous. Otherwise, it will be synchronous by default.\\\\n\\\\n Default value: 2.0\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Delete all of your jobs in output status with a job name\\\\n starting with \\\\\\"ibmuser\\\\\\":\\\\n\\\\n $ zowe zos-jobs delete old-jobs -p \\\\\\"ibmuser*\\\\\\"\\\\n\\\\n\\" }" `; diff --git a/packages/cli/__tests__/zosjobs/__integration__/search/__scripts__/job/job_help.sh b/packages/cli/__tests__/zosjobs/__integration__/search/__scripts__/job/job_help.sh new file mode 100755 index 0000000000..29cafbcb36 --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__integration__/search/__scripts__/job/job_help.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -e + +zowe zos-jobs search job -h +if [ $? -gt 0 ] +then + exit $? +fi + +zowe zos-jobs search job --help --response-format-json +exit $? \ No newline at end of file diff --git a/packages/cli/__tests__/zosjobs/__integration__/search/__scripts__/job/job_syntax_invalid_parm.sh b/packages/cli/__tests__/zosjobs/__integration__/search/__scripts__/job/job_syntax_invalid_parm.sh new file mode 100755 index 0000000000..6432ed0018 --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__integration__/search/__scripts__/job/job_syntax_invalid_parm.sh @@ -0,0 +1,3 @@ +#!/bin/bash +zowe zos-jobs search job "JOB123" blah --host fakehost --user fakeuser --password fakepass +exit $? \ No newline at end of file diff --git a/packages/cli/__tests__/zosjobs/__integration__/search/__scripts__/job/job_syntax_missing_parms.sh b/packages/cli/__tests__/zosjobs/__integration__/search/__scripts__/job/job_syntax_missing_parms.sh new file mode 100755 index 0000000000..2787daf8c7 --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__integration__/search/__scripts__/job/job_syntax_missing_parms.sh @@ -0,0 +1,3 @@ +#!/bin/bash +zowe zos-jobs search job "job123" --host fakehost --user fakeuser --password fakepass +exit $? diff --git a/packages/cli/__tests__/zosjobs/__integration__/search/__scripts__/search_help.sh b/packages/cli/__tests__/zosjobs/__integration__/search/__scripts__/search_help.sh new file mode 100755 index 0000000000..b7c4c73020 --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__integration__/search/__scripts__/search_help.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -e + +zowe zos-jobs search -h +if [ $? -gt 0 ] +then + exit $? +fi + +zowe zos-jobs search --help --response-format-json +exit $? \ No newline at end of file diff --git a/packages/cli/__tests__/zosjobs/__integration__/search/__snapshots__/cli.zos-jobs.search.integration.test.ts.snap b/packages/cli/__tests__/zosjobs/__integration__/search/__snapshots__/cli.zos-jobs.search.integration.test.ts.snap new file mode 100644 index 0000000000..0fa3ed8925 --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__integration__/search/__snapshots__/cli.zos-jobs.search.integration.test.ts.snap @@ -0,0 +1,49 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`zos-jobs search command should display the help 1`] = ` +" + DESCRIPTION + ----------- + + Search the spool output of a job. + + USAGE + ----- + + zowe zos-jobs search + + Where is one of the following: + + COMMANDS + -------- + + job Search the spool output of a job. + + GLOBAL OPTIONS + -------------- + + --help-examples (boolean) + + Display examples for all the commands in a group + + --response-format-json | --rfj (boolean) + + Produce JSON formatted data from a command + + --help | -h (boolean) + + Display help text + + --help-web | --hw (boolean) + + Display HTML help in browser + +{ + \\"success\\": true, + \\"exitCode\\": 0, + \\"message\\": \\"The help was constructed for command: search.\\", + \\"stdout\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Search the spool output of a job.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs search \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n job Search the spool output of a job.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", + \\"stderr\\": \\"\\", + \\"data\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Search the spool output of a job.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs search \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n job Search the spool output of a job.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" +}" +`; diff --git a/packages/cli/__tests__/zosjobs/__integration__/search/__snapshots__/cli.zos-jobs.search.job.integration.test.ts.snap b/packages/cli/__tests__/zosjobs/__integration__/search/__snapshots__/cli.zos-jobs.search.job.integration.test.ts.snap new file mode 100644 index 0000000000..f577dbc399 --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__integration__/search/__snapshots__/cli.zos-jobs.search.job.integration.test.ts.snap @@ -0,0 +1,194 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`zos-jobs search job command should display the help 1`] = ` +" + COMMAND NAME + ------------ + + job + + DESCRIPTION + ----------- + + Search the spool output of a job. + + USAGE + ----- + + zowe zos-jobs search job [options] + + POSITIONAL ARGUMENTS + -------------------- + + jobname (string) + + The job name to search. Wildcards are accepted for the job name. You can use, + for example \\"USERJOB*\\" to search all jobs that start with USERJOB. + + OPTIONS + ------- + + --search-string | --string (string) + + The string to search for in the spool output. + + --search-regex | --regex (string) + + The regular expression to search for in the spool output. + + --case-insensitive | --ci (boolean) + + The search is case insensitive or not. + + Default value: true + + --search-limit | --sl (number) + + The maximum number of matching lines to return for an individual spool file. + + Default value: 100 + + --file-limit | --fl (number) + + The maximum number of spool files to search. + + Default value: 100 + + ZOSMF CONNECTION OPTIONS + ------------------------ + + --host | -H (string) + + The z/OSMF server host name. + + --port | -P (number) + + The z/OSMF server port. + + Default value: 443 + + --user | -u (string) + + Mainframe (z/OSMF) user name, which can be the same as your TSO login. + + --password | --pass | --pw (string) + + Mainframe (z/OSMF) password, which can be the same as your TSO password. + + --reject-unauthorized | --ru (boolean) + + Reject self-signed certificates. + + Default value: true + + --base-path | --bp (string) + + The base path for your API mediation layer instance. Specify this option to + prepend the base path to all z/OSMF resources when making REST requests. Do not + specify this option if you are not using an API mediation layer. + + --protocol (string) + + The protocol used (HTTP or HTTPS) + + Default value: https + Allowed values: http, https + + --cert-file (local file path) + + The file path to a certificate file to use for authentication + + --cert-key-file (local file path) + + The file path to a certificate key file to use for authentication + + PROFILE OPTIONS + --------------- + + --zosmf-profile | --zosmf-p (string) + + The name of a (zosmf) profile to load for this command execution. + + --base-profile | --base-p (string) + + The name of a (base) profile to load for this command execution. + + BASE CONNECTION OPTIONS + ----------------------- + + --token-type | --tt (string) + + The type of token to get and use for the API. Omit this option to use the + default token type, which is provided by 'zowe auth login'. + + --token-value | --tv (string) + + The value of the token to pass to the API. + + GLOBAL OPTIONS + -------------- + + --show-inputs-only (boolean) + + Show command inputs and do not run the command + + --response-format-json | --rfj (boolean) + + Produce JSON formatted data from a command + + --help | -h (boolean) + + Display help text + + --help-web | --hw (boolean) + + Display HTML help in browser + + EXAMPLES + -------- + + - Search all jobs named USERJOB for the string \\"RC=0000\\": + + $ zowe zos-jobs search job \\"USERJOB\\" --search-string \\"RC=0000\\" + + - Search all jobs that start with USER for the string + \\"ENDED\\": + + $ zowe zos-jobs search job \\"USER*\\" --search-string \\"ENDED\\" + + - Search all jobs named USERJOB for the string \\"COND CODE\\", + with the options case sensitive and a search limit of 5: + + $ zowe zos-jobs search job \\"USERJOB\\" --search-string \\"COND CODE\\" --case-insensitive false --search-limit 5 + +{ + \\"success\\": true, + \\"exitCode\\": 0, + \\"message\\": \\"The help was constructed for command: job.\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n job\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Search the spool output of a job.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs search job [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n jobname\\\\t\\\\t (string)\\\\n\\\\n The job name to search. Wildcards are accepted for the job name. You can use,\\\\n for example \\\\\\"USERJOB*\\\\\\" to search all jobs that start with USERJOB.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --search-string | --string (string)\\\\n\\\\n The string to search for in the spool output.\\\\n\\\\n --search-regex | --regex (string)\\\\n\\\\n The regular expression to search for in the spool output.\\\\n\\\\n --case-insensitive | --ci (boolean)\\\\n\\\\n The search is case insensitive or not.\\\\n\\\\n Default value: true\\\\n\\\\n --search-limit | --sl (number)\\\\n\\\\n The maximum number of matching lines to return for an individual spool file.\\\\n\\\\n Default value: 100\\\\n\\\\n --file-limit | --fl (number)\\\\n\\\\n The maximum number of spool files to search.\\\\n\\\\n Default value: 100\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Search all jobs named USERJOB for the string \\\\\\"RC=0000\\\\\\":\\\\n\\\\n $ zowe zos-jobs search job \\\\\\"USERJOB\\\\\\" --search-string \\\\\\"RC=0000\\\\\\"\\\\n\\\\n - Search all jobs that start with USER for the string\\\\n \\\\\\"ENDED\\\\\\":\\\\n\\\\n $ zowe zos-jobs search job \\\\\\"USER*\\\\\\" --search-string \\\\\\"ENDED\\\\\\"\\\\n\\\\n - Search all jobs named USERJOB for the string \\\\\\"COND CODE\\\\\\",\\\\n with the options case sensitive and a search limit of 5:\\\\n\\\\n $ zowe zos-jobs search job \\\\\\"USERJOB\\\\\\" --search-string \\\\\\"COND CODE\\\\\\" --case-insensitive false --search-limit 5\\\\n\\\\n\\", + \\"stderr\\": \\"\\", + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n job\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Search the spool output of a job.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-jobs search job [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n jobname\\\\t\\\\t (string)\\\\n\\\\n The job name to search. Wildcards are accepted for the job name. You can use,\\\\n for example \\\\\\"USERJOB*\\\\\\" to search all jobs that start with USERJOB.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --search-string | --string (string)\\\\n\\\\n The string to search for in the spool output.\\\\n\\\\n --search-regex | --regex (string)\\\\n\\\\n The regular expression to search for in the spool output.\\\\n\\\\n --case-insensitive | --ci (boolean)\\\\n\\\\n The search is case insensitive or not.\\\\n\\\\n Default value: true\\\\n\\\\n --search-limit | --sl (number)\\\\n\\\\n The maximum number of matching lines to return for an individual spool file.\\\\n\\\\n Default value: 100\\\\n\\\\n --file-limit | --fl (number)\\\\n\\\\n The maximum number of spool files to search.\\\\n\\\\n Default value: 100\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Search all jobs named USERJOB for the string \\\\\\"RC=0000\\\\\\":\\\\n\\\\n $ zowe zos-jobs search job \\\\\\"USERJOB\\\\\\" --search-string \\\\\\"RC=0000\\\\\\"\\\\n\\\\n - Search all jobs that start with USER for the string\\\\n \\\\\\"ENDED\\\\\\":\\\\n\\\\n $ zowe zos-jobs search job \\\\\\"USER*\\\\\\" --search-string \\\\\\"ENDED\\\\\\"\\\\n\\\\n - Search all jobs named USERJOB for the string \\\\\\"COND CODE\\\\\\",\\\\n with the options case sensitive and a search limit of 5:\\\\n\\\\n $ zowe zos-jobs search job \\\\\\"USERJOB\\\\\\" --search-string \\\\\\"COND CODE\\\\\\" --case-insensitive false --search-limit 5\\\\n\\\\n\\" +}" +`; + +exports[`zos-jobs search job command syntax errors should occur if an extra unknown option is specified 1`] = ` +"Unable to perform this operation due to the following problem. +Unknown argument: blah +Command failed due to improper syntax +Command entered: \\"zos-jobs search job JOB123 blah --host fakehost --user fakeuser --password fakepass\\" +Available commands are \\"job\\". +Use \\"zowe zos-jobs search --help\\" to view groups, commands, and options. + +Response From Service +Error: Unknown argument: blah + +Diagnostic Information +Unknown argument: blah +" +`; + +exports[`zos-jobs search job command syntax errors should occur if any search parameter is missing 1`] = ` +"Unable to perform this operation due to the following problem. +You must specify either the \`--search-string\` or \`--search-regex\` option +" +`; diff --git a/packages/cli/__tests__/zosjobs/__integration__/search/cli.zos-jobs.search.integration.test.ts b/packages/cli/__tests__/zosjobs/__integration__/search/cli.zos-jobs.search.integration.test.ts new file mode 100644 index 0000000000..c5a9d264ca --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__integration__/search/cli.zos-jobs.search.integration.test.ts @@ -0,0 +1,34 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ITestEnvironment, runCliScript } from "@zowe/cli-test-utils"; +import { TestEnvironment } from "../../../../../../__tests__/__src__/environment/TestEnvironment"; +import { ITestPropertiesSchema } from "../../../../../../__tests__/__src__/properties/ITestPropertiesSchema"; + +// Test Environment populated in the beforeAll(); +let TEST_ENVIRONMENT: ITestEnvironment; + +describe("zos-jobs search command", () => { + // Create the unique test environment + beforeAll(async () => { + TEST_ENVIRONMENT = await TestEnvironment.setUp({ + testName: "zos_jobs_search_command", + skipProperties: true + }); + }); + + it("should display the help", () => { + const response = runCliScript(__dirname + "/__scripts__/search_help.sh", TEST_ENVIRONMENT); + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toMatchSnapshot(); + }); +}); diff --git a/packages/cli/__tests__/zosjobs/__integration__/search/cli.zos-jobs.search.job.integration.test.ts b/packages/cli/__tests__/zosjobs/__integration__/search/cli.zos-jobs.search.job.integration.test.ts new file mode 100644 index 0000000000..c73ee9c115 --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__integration__/search/cli.zos-jobs.search.job.integration.test.ts @@ -0,0 +1,64 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ITestEnvironment, runCliScript } from "@zowe/cli-test-utils"; +import { TestEnvironment } from "../../../../../../__tests__/__src__/environment/TestEnvironment"; +import { ITestPropertiesSchema } from "../../../../../../__tests__/__src__/properties/ITestPropertiesSchema"; + +// Test Environment populated in the beforeAll(); +let TEST_ENVIRONMENT: ITestEnvironment; + +describe("zos-jobs search job command", () => { + // Create the unique test environment + beforeAll(async () => { + TEST_ENVIRONMENT = await TestEnvironment.setUp({ + testName: "zos_jobs_search_job_content_command", + skipProperties: true + }); + }); + + afterAll(async () => { + await TestEnvironment.cleanUp(TEST_ENVIRONMENT); + }); + + it("should display the help", () => { + const response = runCliScript(__dirname + "/__scripts__/job/job_help.sh", + TEST_ENVIRONMENT); + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toMatchSnapshot(); + }); + + describe("syntax errors", () => { + it("should occur if any search parameter is missing", () => { + const response = runCliScript(__dirname + "/__scripts__/job/job_syntax_missing_parms.sh", + TEST_ENVIRONMENT); + expect(response.stdout.toString()).toBe(""); + expect(response.status).toBe(1); + expect(response.stderr.toString()).toMatchSnapshot(); + }); + + it("should occur if an extra unknown option is specified", () => { + const response = runCliScript(__dirname + "/__scripts__/job/job_syntax_invalid_parm.sh", + TEST_ENVIRONMENT); + expect(response.stdout.toString()).toBe(""); + expect(response.status).toBe(1); + expect(response.stderr.toString()).toContain('Unknown argument: blah'); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Command entered: "zos-jobs search job JOB123 blah ' + + '--host fakehost --user fakeuser --password fakepass"'); + expect(response.stderr.toString()).toContain('Available commands are "job".'); + expect(response.stderr.toString()).toContain('Use "zowe zos-jobs search --help" to view groups, commands, and options.'); + expect(response.stderr.toString()).toMatchSnapshot(); + }); + }); + +}); diff --git a/packages/cli/__tests__/zosjobs/__integration__/submit/data-set/__snapshots__/cli.zos-jobs.submit.data-set.integration.test.ts.snap b/packages/cli/__tests__/zosjobs/__integration__/submit/data-set/__snapshots__/cli.zos-jobs.submit.data-set.integration.test.ts.snap index 906d9e831c..b050523724 100644 --- a/packages/cli/__tests__/zosjobs/__integration__/submit/data-set/__snapshots__/cli.zos-jobs.submit.data-set.integration.test.ts.snap +++ b/packages/cli/__tests__/zosjobs/__integration__/submit/data-set/__snapshots__/cli.zos-jobs.submit.data-set.integration.test.ts.snap @@ -217,18 +217,6 @@ exports[`zos-jobs submit data-set command should display the help 1`] = ` }" `; -exports[`zos-jobs submit data-set command syntax errors should occur if an extra unknown option is specified 1`] = ` -"Command Error: -Unknown argument: blah -Command failed due to improper syntax -Command entered: \\"zos-jobs submit data-set DATA.SET blah\\" -Available commands are \\"data-set, local-file, stdin, uss-file\\". -Use \\"zowe zos-jobs submit --help\\" to view groups, commands, and options. -Error Details: -Unknown argument: blah -" -`; - exports[`zos-jobs submit data-set command syntax errors should occur if both --wait-for-active and --directory is specified 1`] = ` " Syntax Error: diff --git a/packages/cli/__tests__/zosjobs/__integration__/submit/data-set/cli.zos-jobs.submit.data-set.integration.test.ts b/packages/cli/__tests__/zosjobs/__integration__/submit/data-set/cli.zos-jobs.submit.data-set.integration.test.ts index 73675ad166..8eff72ee9e 100644 --- a/packages/cli/__tests__/zosjobs/__integration__/submit/data-set/cli.zos-jobs.submit.data-set.integration.test.ts +++ b/packages/cli/__tests__/zosjobs/__integration__/submit/data-set/cli.zos-jobs.submit.data-set.integration.test.ts @@ -57,7 +57,11 @@ describe("zos-jobs submit data-set command", () => { const response = runCliScript(__dirname + "/__scripts__/submit_syntax_invalid_parm.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); expect(response.stdout.toString()).toBe(""); - expect(response.stderr.toString()).toMatchSnapshot(); + expect(response.stderr.toString()).toContain("Unknown argument: blah"); + expect(response.stderr.toString()).toContain("Command failed due to improper syntax"); + expect(response.stderr.toString()).toContain('Command entered: "zos-jobs submit data-set DATA.SET blah"'); + expect(response.stderr.toString()).toContain('Available commands are "data-set, local-file, stdin, uss-file".'); + expect(response.stderr.toString()).toContain('Use "zowe zos-jobs submit --help" to view groups, commands, and options.'); }); it("should occur if both --wait-for-active and --directory is specified", () => { diff --git a/packages/cli/__tests__/zosjobs/__integration__/submit/local-file/__snapshots__/cli.zos-jobs.submit.local-file.integration.test.ts.snap b/packages/cli/__tests__/zosjobs/__integration__/submit/local-file/__snapshots__/cli.zos-jobs.submit.local-file.integration.test.ts.snap index be6556fa5f..87164ff335 100644 --- a/packages/cli/__tests__/zosjobs/__integration__/submit/local-file/__snapshots__/cli.zos-jobs.submit.local-file.integration.test.ts.snap +++ b/packages/cli/__tests__/zosjobs/__integration__/submit/local-file/__snapshots__/cli.zos-jobs.submit.local-file.integration.test.ts.snap @@ -256,18 +256,6 @@ Use \\"zowe zos-jobs submit local-file --help\\" to view command description, us " `; -exports[`zos-jobs submit local-file command syntax errors should occur if an extra unknown option is specified 1`] = ` -"Command Error: -Unknown argument: blah -Command failed due to improper syntax -Command entered: \\"zos-jobs submit local-file ../../../../packages/cli/__tests__/zosjobs/__integration__/submit/local-file/testFileOfLocalJCL.txt blah\\" -Available commands are \\"data-set, local-file, stdin, uss-file\\". -Use \\"zowe zos-jobs submit --help\\" to view groups, commands, and options. -Error Details: -Unknown argument: blah -" -`; - exports[`zos-jobs submit local-file command syntax errors should occur if the local file name is missing 1`] = ` " Syntax Error: diff --git a/packages/cli/__tests__/zosjobs/__integration__/submit/local-file/cli.zos-jobs.submit.local-file.integration.test.ts b/packages/cli/__tests__/zosjobs/__integration__/submit/local-file/cli.zos-jobs.submit.local-file.integration.test.ts index b3c872f19e..c70097a608 100644 --- a/packages/cli/__tests__/zosjobs/__integration__/submit/local-file/cli.zos-jobs.submit.local-file.integration.test.ts +++ b/packages/cli/__tests__/zosjobs/__integration__/submit/local-file/cli.zos-jobs.submit.local-file.integration.test.ts @@ -40,7 +40,6 @@ describe("zos-jobs submit local-file command", () => { const response = runCliScript(__dirname + "/__scripts__/submit_invalid_local_file.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); - expect(response.stderr.toString().toLowerCase()).toContain("error"); expect(response.stderr.toString().toLowerCase()).toContain("no such file"); }); @@ -58,7 +57,12 @@ describe("zos-jobs submit local-file command", () => { TEST_ENVIRONMENT, [relDirname + "/testFileOfLocalJCL.txt"]); expect(response.status).toBe(1); expect(response.stdout.toString()).toBe(""); - expect(response.stderr.toString()).toMatchSnapshot(); + expect(response.stderr.toString()).toContain("Unknown argument: blah"); + expect(response.stderr.toString()).toContain("Command failed due to improper syntax"); + expect(response.stderr.toString()).toContain('Command entered: "zos-jobs submit local-file ' + + '../../../../packages/cli/__tests__/zosjobs/__integration__/submit/local-file/testFileOfLocalJCL.txt blah"'); + expect(response.stderr.toString()).toContain('Available commands are "data-set, local-file, stdin, uss-file".'); + expect(response.stderr.toString()).toContain('Use "zowe zos-jobs submit --help" to view groups, commands, and options.'); }); it("should occur if --wfa and --directory are both specified", () => { diff --git a/packages/cli/__tests__/zosjobs/__integration__/submit/uss-file/__snapshots__/cli.zos-jobs.submit.uss-file.integration.test.ts.snap b/packages/cli/__tests__/zosjobs/__integration__/submit/uss-file/__snapshots__/cli.zos-jobs.submit.uss-file.integration.test.ts.snap index 7290ae8f08..e325ec6037 100644 --- a/packages/cli/__tests__/zosjobs/__integration__/submit/uss-file/__snapshots__/cli.zos-jobs.submit.uss-file.integration.test.ts.snap +++ b/packages/cli/__tests__/zosjobs/__integration__/submit/uss-file/__snapshots__/cli.zos-jobs.submit.uss-file.integration.test.ts.snap @@ -209,18 +209,6 @@ exports[`zos-jobs submit uss-file command should display the help 1`] = ` }" `; -exports[`zos-jobs submit uss-file command syntax errors should occur if an extra unknown option is specified 1`] = ` -"Command Error: -Unknown argument: blah -Command failed due to improper syntax -Command entered: \\"zos-jobs submit uss-file /a/ibmuser/ussfile.txt blah\\" -Available commands are \\"data-set, local-file, stdin, uss-file\\". -Use \\"zowe zos-jobs submit --help\\" to view groups, commands, and options. -Error Details: -Unknown argument: blah -" -`; - exports[`zos-jobs submit uss-file command syntax errors should occur if both --wait-for-active and --directory is specified 1`] = ` " Syntax Error: diff --git a/packages/cli/__tests__/zosjobs/__integration__/submit/uss-file/cli.zos-jobs.submit.uss-file.integration.test.ts b/packages/cli/__tests__/zosjobs/__integration__/submit/uss-file/cli.zos-jobs.submit.uss-file.integration.test.ts index 65ef063339..d5475222fa 100644 --- a/packages/cli/__tests__/zosjobs/__integration__/submit/uss-file/cli.zos-jobs.submit.uss-file.integration.test.ts +++ b/packages/cli/__tests__/zosjobs/__integration__/submit/uss-file/cli.zos-jobs.submit.uss-file.integration.test.ts @@ -57,7 +57,12 @@ describe("zos-jobs submit uss-file command", () => { const response = runCliScript(__dirname + "/__scripts__/submit_syntax_invalid_parm.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); expect(response.stdout.toString()).toBe(""); - expect(response.stderr.toString()).toMatchSnapshot(); + expect(response.stderr.toString()).toContain("Unknown argument: blah"); + expect(response.stderr.toString()).toContain("Command failed due to improper syntax"); + expect(response.stderr.toString()).toContain('Command entered: "zos-jobs submit uss-file ' + + '/a/ibmuser/ussfile.txt blah"'); + expect(response.stderr.toString()).toContain('Available commands are "data-set, local-file, stdin, uss-file".'); + expect(response.stderr.toString()).toContain('Use "zowe zos-jobs submit --help" to view groups, commands, and options.'); }); it("should occur if both --wait-for-active and --directory is specified", () => { diff --git a/packages/cli/__tests__/zosjobs/__integration__/view/__snapshots__/cli.zos-jobs.view.all-spool-content.integration.test.ts.snap b/packages/cli/__tests__/zosjobs/__integration__/view/__snapshots__/cli.zos-jobs.view.all-spool-content.integration.test.ts.snap index 3a8d3e01df..3c174ca0d9 100644 --- a/packages/cli/__tests__/zosjobs/__integration__/view/__snapshots__/cli.zos-jobs.view.all-spool-content.integration.test.ts.snap +++ b/packages/cli/__tests__/zosjobs/__integration__/view/__snapshots__/cli.zos-jobs.view.all-spool-content.integration.test.ts.snap @@ -143,13 +143,17 @@ exports[`zos-jobs view all-spool-content command should display the help 1`] = ` `; exports[`zos-jobs view all-spool-content command syntax errors should occur if an extra unknown option is specified 1`] = ` -"Command Error: +"Unable to perform this operation due to the following problem. Unknown argument: blah Command failed due to improper syntax Command entered: \\"zos-jobs view all-spool-content JOB123 blah --host fakehost --user fakeuser --password fakepass\\" Available commands are \\"all-spool-content, job-status-by-jobid, spool-file-by-id\\". Use \\"zowe zos-jobs view --help\\" to view groups, commands, and options. -Error Details: + +Response From Service +Error: Unknown argument: blah + +Diagnostic Information Unknown argument: blah " `; diff --git a/packages/cli/__tests__/zosjobs/__integration__/view/__snapshots__/cli.zos-jobs.view.job-status-by-jobid.integration.test.ts.snap b/packages/cli/__tests__/zosjobs/__integration__/view/__snapshots__/cli.zos-jobs.view.job-status-by-jobid.integration.test.ts.snap index e6813a5b06..654cefe2b4 100644 --- a/packages/cli/__tests__/zosjobs/__integration__/view/__snapshots__/cli.zos-jobs.view.job-status-by-jobid.integration.test.ts.snap +++ b/packages/cli/__tests__/zosjobs/__integration__/view/__snapshots__/cli.zos-jobs.view.job-status-by-jobid.integration.test.ts.snap @@ -176,18 +176,6 @@ exports[`zos-jobs view job-status-by-jobid command should display the help 1`] = }" `; -exports[`zos-jobs view job-status-by-jobid command syntax errors should occur if an extra unknown option is specified 1`] = ` -"Command Error: -Unknown argument: blah -Command failed due to improper syntax -Command entered: \\"zos-jobs view job-status-by-jobid JOB123 blah --host fakehost --user fakeuser --password fakepass\\" -Available commands are \\"all-spool-content, job-status-by-jobid, spool-file-by-id\\". -Use \\"zowe zos-jobs view --help\\" to view groups, commands, and options. -Error Details: -Unknown argument: blah -" -`; - exports[`zos-jobs view job-status-by-jobid command syntax errors should occur if the jobid is missing 1`] = ` " Syntax Error: diff --git a/packages/cli/__tests__/zosjobs/__integration__/view/cli.zos-jobs.view.all-spool-content.integration.test.ts b/packages/cli/__tests__/zosjobs/__integration__/view/cli.zos-jobs.view.all-spool-content.integration.test.ts index 775ae98f48..cbc1e862f9 100644 --- a/packages/cli/__tests__/zosjobs/__integration__/view/cli.zos-jobs.view.all-spool-content.integration.test.ts +++ b/packages/cli/__tests__/zosjobs/__integration__/view/cli.zos-jobs.view.all-spool-content.integration.test.ts @@ -51,6 +51,12 @@ describe("zos-jobs view all-spool-content command", () => { TEST_ENVIRONMENT); expect(response.stdout.toString()).toBe(""); expect(response.status).toBe(1); + expect(response.stderr.toString()).toContain('Unknown argument: blah'); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Command entered: "zos-jobs view all-spool-content JOB123 blah ' + + '--host fakehost --user fakeuser --password fakepass"'); + expect(response.stderr.toString()).toContain('Available commands are "all-spool-content, job-status-by-jobid, spool-file-by-id".'); + expect(response.stderr.toString()).toContain('Use "zowe zos-jobs view --help" to view groups, commands, and options.'); expect(response.stderr.toString()).toMatchSnapshot(); }); }); diff --git a/packages/cli/__tests__/zosjobs/__integration__/view/cli.zos-jobs.view.job-status-by-jobid.integration.test.ts b/packages/cli/__tests__/zosjobs/__integration__/view/cli.zos-jobs.view.job-status-by-jobid.integration.test.ts index 055e08ebab..11bba6de2e 100644 --- a/packages/cli/__tests__/zosjobs/__integration__/view/cli.zos-jobs.view.job-status-by-jobid.integration.test.ts +++ b/packages/cli/__tests__/zosjobs/__integration__/view/cli.zos-jobs.view.job-status-by-jobid.integration.test.ts @@ -51,7 +51,12 @@ describe("zos-jobs view job-status-by-jobid command", () => { TEST_ENVIRONMENT); expect(response.stdout.toString()).toBe(""); expect(response.status).toBe(1); - expect(response.stderr.toString()).toMatchSnapshot(); + expect(response.stderr.toString()).toContain('Unknown argument: blah'); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Command entered: "zos-jobs view job-status-by-jobid JOB123 blah ' + + '--host fakehost --user fakeuser --password fakepass"'); + expect(response.stderr.toString()).toContain('Available commands are "all-spool-content, job-status-by-jobid, spool-file-by-id".'); + expect(response.stderr.toString()).toContain('Use "zowe zos-jobs view --help" to view groups, commands, and options.'); }); }); diff --git a/packages/cli/__tests__/zosjobs/__system__/cancel/cli.zos-jobs.cancel.job.system.test.ts b/packages/cli/__tests__/zosjobs/__system__/cancel/cli.zos-jobs.cancel.job.system.test.ts index c2366ea4f9..f83b35c13a 100644 --- a/packages/cli/__tests__/zosjobs/__system__/cancel/cli.zos-jobs.cancel.job.system.test.ts +++ b/packages/cli/__tests__/zosjobs/__system__/cancel/cli.zos-jobs.cancel.job.system.test.ts @@ -44,14 +44,8 @@ describe("zos-jobs cancel job command", () => { const response = runCliScript(__dirname + "/__scripts__/job/not_found.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); expect(response.stdout.toString()).toBe(""); - // TODO:V3_ERR_FORMAT - In V3 remove the following lines - expect(response.stderr.toString()).toContain("Command Error:"); - expect(response.stderr.toString()).toContain("Obtaining job info for a single job id JOB00000 on"); - expect(response.stderr.toString()).toContain("failed: Job not found"); - /* TODO:V3_ERR_FORMAT - Use the following lines instead expect(response.stderr.toString()).toContain("Cannot obtain job info for job id = JOB00000"); expect(response.stderr.toString()).toContain("Zero jobs were returned"); - */ }); it("should surface an error from z/OSMF if the jobid was already canceled", () => { diff --git a/packages/cli/__tests__/zosjobs/__system__/delete/cli.zos-jobs.delete.job.system.test.ts b/packages/cli/__tests__/zosjobs/__system__/delete/cli.zos-jobs.delete.job.system.test.ts index c70924a92c..9d8d74af0d 100644 --- a/packages/cli/__tests__/zosjobs/__system__/delete/cli.zos-jobs.delete.job.system.test.ts +++ b/packages/cli/__tests__/zosjobs/__system__/delete/cli.zos-jobs.delete.job.system.test.ts @@ -33,14 +33,8 @@ describe("zos-jobs delete job command", () => { const response = runCliScript(__dirname + "/__scripts__/job/not_found.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); expect(response.stdout.toString()).toBe(""); - // TODO:V3_ERR_FORMAT - In V3 remove the following lines - expect(response.stderr.toString()).toContain("Command Error:"); - expect(response.stderr.toString()).toContain("Obtaining job info for a single job id JOB00000 on"); - expect(response.stderr.toString()).toContain("failed: Job not found"); - /* TODO:V3_ERR_FORMAT - Use the following lines instead expect(response.stderr.toString()).toContain("Cannot obtain job info for job id = JOB00000"); expect(response.stderr.toString()).toContain("Zero jobs were returned"); - */ }); }); diff --git a/packages/cli/__tests__/zosjobs/__system__/download/cli.zos-jobs.download.output.system.test.ts b/packages/cli/__tests__/zosjobs/__system__/download/cli.zos-jobs.download.output.system.test.ts index 97672996db..f553570fc9 100644 --- a/packages/cli/__tests__/zosjobs/__system__/download/cli.zos-jobs.download.output.system.test.ts +++ b/packages/cli/__tests__/zosjobs/__system__/download/cli.zos-jobs.download.output.system.test.ts @@ -33,14 +33,8 @@ describe("zos-jobs download output command", () => { const response = runCliScript(__dirname + "/__scripts__/download-output/not_found.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); expect(response.stdout.toString()).toBe(""); - // TODO:V3_ERR_FORMAT - In V3 remove the following lines - expect(response.stderr.toString()).toContain("Command Error:"); - expect(response.stderr.toString()).toContain("Obtaining job info for a single job id JOB00000 on"); - expect(response.stderr.toString()).toContain("failed: Job not found"); - /* TODO:V3_ERR_FORMAT - Use the following lines instead expect(response.stderr.toString()).toContain("Cannot obtain job info for job id = JOB00000"); expect(response.stderr.toString()).toContain("Zero jobs were returned"); - */ }); }); diff --git a/packages/cli/__tests__/zosjobs/__system__/list/cli.zos-jobs.list.spool-files-by-jobid.system.test.ts b/packages/cli/__tests__/zosjobs/__system__/list/cli.zos-jobs.list.spool-files-by-jobid.system.test.ts index b13ca31764..b90a2aeb63 100644 --- a/packages/cli/__tests__/zosjobs/__system__/list/cli.zos-jobs.list.spool-files-by-jobid.system.test.ts +++ b/packages/cli/__tests__/zosjobs/__system__/list/cli.zos-jobs.list.spool-files-by-jobid.system.test.ts @@ -61,14 +61,8 @@ describe("zos-jobs list spool-files-by-jobid command", () => { it("should present an error message if the JOBID is not found", () => { const response = runCliScript(__dirname + "/__scripts__/spool-files-by-jobid/not_found.sh", TEST_ENVIRONMENT); expect(response.stdout.toString()).toBe(""); - // TODO:V3_ERR_FORMAT - In V3 remove the following lines - expect(response.stderr.toString()).toContain("Command Error:"); - expect(response.stderr.toString()).toContain("Obtaining job info for a single job id j0"); - expect(response.stderr.toString()).toContain("failed: Job not found"); - /* TODO:V3_ERR_FORMAT - Use the following lines instead expect(response.stderr.toString()).toContain("Cannot obtain job info for job id = j0"); expect(response.stderr.toString()).toContain("Zero jobs were returned"); - */ expect(response.status).toBe(1); }); @@ -76,11 +70,11 @@ describe("zos-jobs list spool-files-by-jobid command", () => { const response = runCliScript(__dirname + "/__scripts__/spool-files-by-jobid/invalid_jobid.sh", TEST_ENVIRONMENT); expect(response.stdout.toString()).toBe(""); const trimmed = trimMessage(response.stderr.toString()); - expect(trimmed).toContain("status 400"); - expect(trimmed).toContain("category: 6"); - expect(trimmed).toContain("reason: 4"); expect(trimmed).toContain("Value of jobid query parameter is not valid"); expect(trimmed).toContain("rc: 4"); + expect(trimmed).toContain("reason: 4"); + expect(trimmed).toContain("category: 6"); + expect(trimmed).toContain("Received HTTP(S) error 400 = Bad Request"); expect(trimmed).toContain("Resource: /zosmf/restjobs/jobs"); expect(trimmed).toContain("Request: GET"); expect(response.status).toBe(1); diff --git a/packages/cli/__tests__/zosjobs/__system__/modify/cli.zos-jobs.modify.job.system.test.ts b/packages/cli/__tests__/zosjobs/__system__/modify/cli.zos-jobs.modify.job.system.test.ts index 4b06a4b5d0..6905d5fd60 100644 --- a/packages/cli/__tests__/zosjobs/__system__/modify/cli.zos-jobs.modify.job.system.test.ts +++ b/packages/cli/__tests__/zosjobs/__system__/modify/cli.zos-jobs.modify.job.system.test.ts @@ -42,7 +42,7 @@ describe("zos-jobs modify job command", () => { const response = runCliScript(__dirname + "/__scripts__/job/bogus_jobid.sh", TEST_ENVIRONMENT); // potential fix needed in imperative to count this type of error as status = 1 expect(response.status).toBe(0); - expect(response.stderr.toString()).toContain("Job not found"); + expect(response.stderr.toString()).toContain("Zero jobs were returned."); }); }); diff --git a/packages/cli/__tests__/zosjobs/__system__/search/__scripts__/job/search_no_job_submit.sh b/packages/cli/__tests__/zosjobs/__system__/search/__scripts__/job/search_no_job_submit.sh new file mode 100644 index 0000000000..ccd3f9f253 --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__system__/search/__scripts__/job/search_no_job_submit.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +zowe jobs search job "$1" $2 +RC=$? +if [ $RC -gt 0 ] +then + echo $STATUS 1>&2 + echo "The search spool job command returned a non-zero rc: $RC" 1>&2 + exit $RC +fi + diff --git a/packages/cli/__tests__/zosjobs/__system__/search/__scripts__/job/search_string_spool_content.sh b/packages/cli/__tests__/zosjobs/__system__/search/__scripts__/job/search_string_spool_content.sh new file mode 100644 index 0000000000..4ee6abe2a9 --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__system__/search/__scripts__/job/search_string_spool_content.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# TODO - delete the job from spool +# Submit the job and ensure the RC is 0 +JOBID="$(zowe jobs submit ds "$1" --wfo true --rff jobid --rft string)" +CMDRC=$? +if [ $CMDRC -gt 0 ] +then + echo $JOBID 1>&2 + echo "Submit returned a non-zero return code" 1>&2 + exit $CMDRC +fi + +zowe jobs search job "$2" --search-string "$3" +RC=$? +if [ $RC -gt 0 ] +then + echo $STATUS 1>&2 + echo "The search spool job command returned a non-zero rc: $RC" 1>&2 + exit $RC +fi + diff --git a/packages/cli/__tests__/zosjobs/__system__/search/cli.zos-jobs.search.job.test.ts b/packages/cli/__tests__/zosjobs/__system__/search/cli.zos-jobs.search.job.test.ts new file mode 100644 index 0000000000..75e39a2d73 --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__system__/search/cli.zos-jobs.search.job.test.ts @@ -0,0 +1,108 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ITestEnvironment, runCliScript } from "@zowe/cli-test-utils"; +import { TestEnvironment } from "../../../../../../__tests__/__src__/environment/TestEnvironment"; +import { ITestPropertiesSchema } from "../../../../../../__tests__/__src__/properties/ITestPropertiesSchema"; +import { Session } from "@zowe/imperative"; + +// Test Environment populated in the beforeAll(); +let TEST_ENVIRONMENT: ITestEnvironment; +let IEFBR14_JOB: string; +let REAL_SESSION: Session; +let ACCOUNT: string; +let JOB_NAME: string; +let NON_HELD_JOBCLASS: string; +let SEARCH_STRING: string; +let REGEX_STRING: string; +let BAD_SEARCH_STRING: string; + +describe("zos-jobs search job command", () => { + // Create the unique test environment + beforeAll(async () => { + TEST_ENVIRONMENT = await TestEnvironment.setUp({ + testName: "zos_jobs_search_job_command", + tempProfileTypes: ["zosmf"] + }); + + IEFBR14_JOB = TEST_ENVIRONMENT.systemTestProperties.zosjobs.iefbr14Member; + const defaultSystem = TEST_ENVIRONMENT.systemTestProperties; + REAL_SESSION = TestEnvironment.createZosmfSession(TEST_ENVIRONMENT); + + ACCOUNT = defaultSystem.tso.account; + const JOB_LENGTH = 6; + JOB_NAME = REAL_SESSION.ISession.user.substring(0, JOB_LENGTH).toUpperCase() + "SF"; + NON_HELD_JOBCLASS = TEST_ENVIRONMENT.systemTestProperties.zosjobs.jobclass; + SEARCH_STRING = "PGM=IEFBR14"; + REGEX_STRING = "IEFBR14|RC=0000"; + BAD_SEARCH_STRING = "bluhbluh"; + + }); + + afterAll(async () => { + await TestEnvironment.cleanUp(TEST_ENVIRONMENT); + }); + + describe("Successful response", () => { + it("should be able to search for a string in every spool file for a job", () => { + const response = runCliScript(__dirname + "/__scripts__/job/search_string_spool_content.sh", + TEST_ENVIRONMENT, [IEFBR14_JOB, JOB_NAME, SEARCH_STRING]); + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain(SEARCH_STRING); + }); + + it("should be able to search for a regex in every spool file for a job", () => { + const argString = "--search-regex \"" + REGEX_STRING + "\""; + const response = runCliScript(__dirname + "/__scripts__/job/search_no_job_submit.sh", + TEST_ENVIRONMENT, [JOB_NAME, argString]); + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain("IEFBR14"); + expect(response.stdout.toString()).toContain("RC=0000"); + }); + + it("should limit the search when the --search-limit and --file-limit options are specified", () => { + const argString = "--search-string \"" + SEARCH_STRING + "\" --search-limit 5 --file-limit 3"; + const response = runCliScript(__dirname + "/__scripts__/job/search_no_job_submit.sh", + TEST_ENVIRONMENT, [JOB_NAME, argString]); + expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain(SEARCH_STRING); + }); + }); + + describe("error handling", () => { + it("should return a status code of 1 if the string is not found", () => { + const argString = "--search-string \"" + BAD_SEARCH_STRING + "\""; + const response = runCliScript(__dirname + "/__scripts__/job/search_no_job_submit.sh", + TEST_ENVIRONMENT, [JOB_NAME, argString]); + expect(response.stderr.toString()).toContain("The search spool job command returned a non-zero rc: 1"); + expect(response.status).toBe(1); + expect(response.stdout.toString()).toBe(""); + }); + + it("should fail if no parameters are passed", () => { + const response = runCliScript(__dirname + "/__scripts__/job/search_no_job_submit.sh", + TEST_ENVIRONMENT, [JOB_NAME, ""]); + expect(response.stderr.toString()).toContain("You must specify either the `--search-string` or `--search-regex` option"); + expect(response.status).toBe(1); + }); + + it("should fail if --search-string and --search-regex parameters are passed", () => { + const argString = "--search-regex \"" + REGEX_STRING +"\" --search-string \"" + SEARCH_STRING + "\""; + const response = runCliScript(__dirname + "/__scripts__/job/search_no_job_submit.sh", + TEST_ENVIRONMENT, [JOB_NAME, argString]); + expect(response.stderr.toString()).toContain("You must specify either the `--search-string` or `--search-regex` option"); + expect(response.status).toBe(1); + }); + }); +}); diff --git a/packages/cli/__tests__/zosjobs/__system__/view/cli.zos-jobs.view.all-spool-content.system.test.ts b/packages/cli/__tests__/zosjobs/__system__/view/cli.zos-jobs.view.all-spool-content.system.test.ts index 934a6265f4..ebd08c8d5d 100644 --- a/packages/cli/__tests__/zosjobs/__system__/view/cli.zos-jobs.view.all-spool-content.system.test.ts +++ b/packages/cli/__tests__/zosjobs/__system__/view/cli.zos-jobs.view.all-spool-content.system.test.ts @@ -106,14 +106,8 @@ describe("zos-jobs view all-spool-content command", () => { TEST_ENVIRONMENT); expect(response.stdout.toString()).toBe(""); expect(response.status).toBe(1); - // TODO:V3_ERR_FORMAT - In V3 remove the following lines - expect(response.stderr.toString()).toContain("Command Error:"); - expect(response.stderr.toString()).toContain("Obtaining job info for a single job id JOB00000 on"); - expect(response.stderr.toString()).toContain("failed: Job not found"); - /* TODO:V3_ERR_FORMAT - Use the following lines instead expect(response.stderr.toString()).toContain("Cannot obtain job info for job id = JOB00000"); expect(response.stderr.toString()).toContain("Zero jobs were returned"); - */ }); }); }); diff --git a/packages/cli/__tests__/zosjobs/__system__/view/cli.zos-jobs.view.job-status-by-jobid.system.test.ts b/packages/cli/__tests__/zosjobs/__system__/view/cli.zos-jobs.view.job-status-by-jobid.system.test.ts index b9078a46e9..4c614e5f83 100644 --- a/packages/cli/__tests__/zosjobs/__system__/view/cli.zos-jobs.view.job-status-by-jobid.system.test.ts +++ b/packages/cli/__tests__/zosjobs/__system__/view/cli.zos-jobs.view.job-status-by-jobid.system.test.ts @@ -135,14 +135,8 @@ describe("zos-jobs view job-status-by-jobid command", () => { TEST_ENVIRONMENT); expect(response.stdout.toString()).toBe(""); expect(response.status).toBe(1); - // TODO:V3_ERR_FORMAT - In V3 remove the following lines - expect(response.stderr.toString()).toContain("Command Error:"); - expect(response.stderr.toString()).toContain("Obtaining job info for a single job id J0 on"); - expect(response.stderr.toString()).toContain("failed: Job not found"); - /* TODO:V3_ERR_FORMAT - Use the following lines instead expect(response.stderr.toString()).toContain("Cannot obtain job info for job id = J0"); expect(response.stderr.toString()).toContain("Zero jobs were returned"); - */ }); }); }); diff --git a/packages/cli/__tests__/zosjobs/__system__/view/cli.zos-jobs.view.spool-file-by-id.system.test.ts b/packages/cli/__tests__/zosjobs/__system__/view/cli.zos-jobs.view.spool-file-by-id.system.test.ts index 14d5c6cd64..b50c4bec4b 100644 --- a/packages/cli/__tests__/zosjobs/__system__/view/cli.zos-jobs.view.spool-file-by-id.system.test.ts +++ b/packages/cli/__tests__/zosjobs/__system__/view/cli.zos-jobs.view.spool-file-by-id.system.test.ts @@ -127,14 +127,8 @@ describe("zos-jobs view spool-file-by-id command", () => { TEST_ENVIRONMENT); expect(response.stdout.toString()).toBe(""); expect(response.status).toBe(1); - // TODO:V3_ERR_FORMAT - In V3 remove the following lines - expect(response.stderr.toString()).toContain("Command Error:"); - expect(response.stderr.toString()).toContain("Obtaining job info for a single job id J0 on"); - expect(response.stderr.toString()).toContain("failed: Job not found"); - /* TODO:V3_ERR_FORMAT - Use the following lines instead expect(response.stderr.toString()).toContain("Cannot obtain job info for job id = J0"); expect(response.stderr.toString()).toContain("Zero jobs were returned"); - */ }); it("should surface an error if the spool file ID does not exist", () => { @@ -144,13 +138,7 @@ describe("zos-jobs view spool-file-by-id command", () => { expect(response.status).toBe(1); expect(response.stderr.toString()).toContain("does not contain spool file id 9999"); expect(response.stderr.toString()).toMatch(/Request: +GET/); - // TODO:V3_ERR_FORMAT - In V3 remove the following lines - expect(response.stderr.toString()).toContain("Command Error:"); - expect(response.stderr.toString()).toContain("z/OSMF REST API Error:"); - expect(response.stderr.toString()).toContain("Error Details:"); - /* TODO:V3_ERR_FORMAT - Use the following lines instead expect(response.stderr.toString()).toContain("HTTP(S) error 400 = Bad Request"); - */ }); }); }); diff --git a/packages/cli/__tests__/zosjobs/__unit__/cancel/job/Job.handler.unit.test.ts b/packages/cli/__tests__/zosjobs/__unit__/cancel/job/Job.handler.unit.test.ts index df8c2da150..4c6a80e43b 100644 --- a/packages/cli/__tests__/zosjobs/__unit__/cancel/job/Job.handler.unit.test.ts +++ b/packages/cli/__tests__/zosjobs/__unit__/cancel/job/Job.handler.unit.test.ts @@ -15,10 +15,7 @@ import { GetJobs, CancelJobs, IJobFeedback } from "@zowe/zos-jobs-for-zowe-sdk"; import { GetJobsData } from "../../../__resources__/GetJobsData"; import * as JobHandler from "../../../../../src/zosjobs/cancel/job/Job.handler"; import * as JobDefinition from "../../../../../src/zosjobs/cancel/job/Job.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; process.env.FORCE_COLOR = "0"; @@ -26,8 +23,7 @@ process.env.FORCE_COLOR = "0"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-jobs", "cancel", "job"], - definition: JobDefinition.JobDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: JobDefinition.JobDefinition }); const DEFAULT_RESPONSE_FEEDBACK: IJobFeedback = { diff --git a/packages/cli/__tests__/zosjobs/__unit__/cancel/job/__snapshots__/Job.definition.unit.test.ts.snap b/packages/cli/__tests__/zosjobs/__unit__/cancel/job/__snapshots__/Job.definition.unit.test.ts.snap index 7604d60dca..af09561c63 100644 --- a/packages/cli/__tests__/zosjobs/__unit__/cancel/job/__snapshots__/Job.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosjobs/__unit__/cancel/job/__snapshots__/Job.definition.unit.test.ts.snap @@ -2,7 +2,7 @@ exports[`zos-jobs cancel job definition should not have changed 1`] = ` Object { - "description": "Cancel a single job by job ID", + "description": "Cancel a single job by job ID.", "examples": Array [ Object { "description": "Cancel job with job ID JOB03456", @@ -17,7 +17,7 @@ Object { "options": Array [ Object { "defaultValue": "2.0", - "description": "Using this option to set X-IBM-Job-Modify-Version to \\"1.0\\" will make the delete job API aynchronous. Otherwise, it will be synchronous by default.", + "description": "Using this option to set X-IBM-Job-Modify-Version to \\"1.0\\" will make the delete job API asynchronous. Otherwise, it will be synchronous by default.", "name": "modify-version", "required": false, "type": "string", diff --git a/packages/cli/__tests__/zosjobs/__unit__/delete/job/Job.handler.unit.test.ts b/packages/cli/__tests__/zosjobs/__unit__/delete/job/Job.handler.unit.test.ts index 4ac9c09ec3..d1945ef98f 100644 --- a/packages/cli/__tests__/zosjobs/__unit__/delete/job/Job.handler.unit.test.ts +++ b/packages/cli/__tests__/zosjobs/__unit__/delete/job/Job.handler.unit.test.ts @@ -15,10 +15,7 @@ import { GetJobs, DeleteJobs, IJobFeedback } from "@zowe/zos-jobs-for-zowe-sdk"; import { GetJobsData } from "../../../__resources__/GetJobsData"; import * as JobHandler from "../../../../../src/zosjobs/delete/job/Job.handler"; import * as JobDefinition from "../../../../../src/zosjobs/delete/job/Job.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; process.env.FORCE_COLOR = "0"; @@ -26,8 +23,7 @@ process.env.FORCE_COLOR = "0"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-jobs", "delete", "job"], - definition: JobDefinition.JobDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: JobDefinition.JobDefinition }); const DEFAULT_RESPONSE_FEEDBACK: IJobFeedback = { diff --git a/packages/cli/__tests__/zosjobs/__unit__/delete/job/__snapshots__/Job.definition.unit.test.ts.snap b/packages/cli/__tests__/zosjobs/__unit__/delete/job/__snapshots__/Job.definition.unit.test.ts.snap index 3ea73b0516..cbd5826b09 100644 --- a/packages/cli/__tests__/zosjobs/__unit__/delete/job/__snapshots__/Job.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosjobs/__unit__/delete/job/__snapshots__/Job.definition.unit.test.ts.snap @@ -2,7 +2,7 @@ exports[`zos-jobs delete job definition should not have changed 1`] = ` Object { - "description": "Delete a single job by job ID", + "description": "Delete a single job by job ID.", "examples": Array [ Object { "description": "Delete job with job ID JOB03456", @@ -17,7 +17,7 @@ Object { "options": Array [ Object { "defaultValue": "2.0", - "description": "Using this option to set X-IBM-Job-Modify-Version to \\"1.0\\" will make the delete job API aynchronous. Otherwise, it will be synchronous by default.", + "description": "Using this option to set X-IBM-Job-Modify-Version to \\"1.0\\" will make the delete job API asynchronous. Otherwise, it will be synchronous by default.", "name": "modify-version", "required": false, "type": "string", diff --git a/packages/cli/__tests__/zosjobs/__unit__/delete/old-jobs/OldJobs.handler.unit.test.ts b/packages/cli/__tests__/zosjobs/__unit__/delete/old-jobs/OldJobs.handler.unit.test.ts index bc43ad6499..608efa2c0d 100644 --- a/packages/cli/__tests__/zosjobs/__unit__/delete/old-jobs/OldJobs.handler.unit.test.ts +++ b/packages/cli/__tests__/zosjobs/__unit__/delete/old-jobs/OldJobs.handler.unit.test.ts @@ -15,10 +15,7 @@ import { GetJobs, DeleteJobs } from "@zowe/zos-jobs-for-zowe-sdk"; import { GetJobsData } from "../../../__resources__/GetJobsData"; import * as OldJobsHandler from "../../../../../src/zosjobs/delete/old-jobs/OldJobs.handler"; import * as OldJobsDefinition from "../../../../../src/zosjobs/delete/old-jobs/OldJobs.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; process.env.FORCE_COLOR = "0"; @@ -26,8 +23,7 @@ process.env.FORCE_COLOR = "0"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-jobs", "delete", "old-jobs"], - definition: OldJobsDefinition.OldJobsDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: OldJobsDefinition.OldJobsDefinition }); describe("delete old-jobs handler tests", () => { diff --git a/packages/cli/__tests__/zosjobs/__unit__/delete/old-jobs/__snapshots__/OldJobs.definition.unit.test.ts.snap b/packages/cli/__tests__/zosjobs/__unit__/delete/old-jobs/__snapshots__/OldJobs.definition.unit.test.ts.snap index e9ff3a6923..99624657e7 100644 --- a/packages/cli/__tests__/zosjobs/__unit__/delete/old-jobs/__snapshots__/OldJobs.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosjobs/__unit__/delete/old-jobs/__snapshots__/OldJobs.definition.unit.test.ts.snap @@ -33,7 +33,7 @@ Object { }, Object { "defaultValue": "2.0", - "description": "Using this option to set X-IBM-Job-Modify-Version to \\"1.0\\" will make the delete job API aynchronous. Otherwise, it will be synchronous by default.", + "description": "Using this option to set X-IBM-Job-Modify-Version to \\"1.0\\" will make the delete job API asynchronous. Otherwise, it will be synchronous by default.", "name": "modify-version", "required": false, "type": "string", diff --git a/packages/cli/__tests__/zosjobs/__unit__/download/download-output/Output.handler.unit.test.ts b/packages/cli/__tests__/zosjobs/__unit__/download/download-output/Output.handler.unit.test.ts index ea7378a4ff..b2bc1e02a9 100644 --- a/packages/cli/__tests__/zosjobs/__unit__/download/download-output/Output.handler.unit.test.ts +++ b/packages/cli/__tests__/zosjobs/__unit__/download/download-output/Output.handler.unit.test.ts @@ -16,10 +16,7 @@ jest.mock("@zowe/zos-jobs-for-zowe-sdk"); import { IHandlerParameters, ImperativeError, Session } from "@zowe/imperative"; import * as OutputHandler from "../../../../../src/zosjobs/download/download-output/Output.handler"; import * as OutputDefinition from "../../../../../src/zosjobs/download/download-output/Output.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; process.env.FORCE_COLOR = "0"; @@ -27,8 +24,7 @@ process.env.FORCE_COLOR = "0"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-jobs", "download", "output"], - definition: OutputDefinition.OutputDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: OutputDefinition.OutputDefinition }); describe("download output handler tests", () => { diff --git a/packages/cli/__tests__/zosjobs/__unit__/list/jobs/Jobs.handler.unit.test.ts b/packages/cli/__tests__/zosjobs/__unit__/list/jobs/Jobs.handler.unit.test.ts index 1dbca8370e..edad84edbc 100644 --- a/packages/cli/__tests__/zosjobs/__unit__/list/jobs/Jobs.handler.unit.test.ts +++ b/packages/cli/__tests__/zosjobs/__unit__/list/jobs/Jobs.handler.unit.test.ts @@ -16,10 +16,7 @@ jest.mock("@zowe/zos-jobs-for-zowe-sdk"); import { IHandlerParameters, ImperativeError, Session } from "@zowe/imperative"; import * as JobsHandler from "../../../../../src/zosjobs/list/jobs/Jobs.handler"; import * as JobsDefinition from "../../../../../src/zosjobs/list/jobs/Jobs.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; process.env.FORCE_COLOR = "0"; @@ -27,8 +24,7 @@ process.env.FORCE_COLOR = "0"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-jobs", "view", "job"], - definition: JobsDefinition.JobsDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: JobsDefinition.JobsDefinition }); describe("list jobs handler tests", () => { diff --git a/packages/cli/__tests__/zosjobs/__unit__/list/spool-files-by-jobid/SpoolFilesByJobid.handler.unit.test.ts b/packages/cli/__tests__/zosjobs/__unit__/list/spool-files-by-jobid/SpoolFilesByJobid.handler.unit.test.ts index 18e8e481d1..88f1d40a60 100644 --- a/packages/cli/__tests__/zosjobs/__unit__/list/spool-files-by-jobid/SpoolFilesByJobid.handler.unit.test.ts +++ b/packages/cli/__tests__/zosjobs/__unit__/list/spool-files-by-jobid/SpoolFilesByJobid.handler.unit.test.ts @@ -15,10 +15,7 @@ import { GetJobs } from "@zowe/zos-jobs-for-zowe-sdk"; import { GetJobsData } from "../../../__resources__/GetJobsData"; import { SpoolFilesByJobidDefinition } from "../../../../../src/zosjobs/list/spool-files-by-jobid/SpoolFilesByJobid.definition"; import * as SpoolFilesHandler from "../../../../../src/zosjobs/list/spool-files-by-jobid/SpoolFilesByJobid.handler"; -import { - UNIT_TEST_PROFILES_ZOSMF, - UNIT_TEST_ZOSMF_PROF_OPTS -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; // Disable coloring for the snapshots @@ -27,8 +24,7 @@ process.env.FORCE_COLOR = "0"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-jobs", "list", "spool-files"], - definition: SpoolFilesByJobidDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: SpoolFilesByJobidDefinition }); describe("zos-jobs list spool-files-by-jobid handler", () => { diff --git a/packages/cli/__tests__/zosjobs/__unit__/modify/job/Job.handler.unit.test.ts b/packages/cli/__tests__/zosjobs/__unit__/modify/job/Job.handler.unit.test.ts index fc0b1a4d2a..b703740e85 100644 --- a/packages/cli/__tests__/zosjobs/__unit__/modify/job/Job.handler.unit.test.ts +++ b/packages/cli/__tests__/zosjobs/__unit__/modify/job/Job.handler.unit.test.ts @@ -14,10 +14,7 @@ import { IHandlerParameters, ImperativeError } from "@zowe/imperative"; import { GetJobs, IJob, IJobFeedback, ModifyJobs } from "@zowe/zos-jobs-for-zowe-sdk"; import * as ModifyDefintion from "../../../../../src/zosjobs/modify/job/Job.definition"; import * as ModifyHandler from "../../../../../src/zosjobs/modify/job/Job.handler"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; process.env.FORCE_COLOR = "0"; @@ -25,8 +22,7 @@ process.env.FORCE_COLOR = "0"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-jobs", "modify", "job"], - definition: ModifyDefintion.JobDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: ModifyDefintion.JobDefinition }); const SAMPLE_COMPLETE_JOB: IJob= { diff --git a/packages/cli/__tests__/zosjobs/__unit__/search/Search.definition.unit.test.ts b/packages/cli/__tests__/zosjobs/__unit__/search/Search.definition.unit.test.ts new file mode 100644 index 0000000000..295f58c599 --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__unit__/search/Search.definition.unit.test.ts @@ -0,0 +1,24 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ICommandDefinition } from "@zowe/imperative"; + +const SEARCH_CHILDREN: number = 1; + +describe("zos-jobs search group definition", () => { + it("should not have changed", () => { + const definition: ICommandDefinition = require("../../../../src/zosjobs/search/Search.definition").SearchDefinition; + expect(definition).toBeDefined(); + expect(definition.children.length).toBe(SEARCH_CHILDREN); + delete definition.children; + expect(definition).toMatchSnapshot(); + }); +}); diff --git a/packages/cli/__tests__/zosjobs/__unit__/search/__snapshots__/Search.definition.unit.test.ts.snap b/packages/cli/__tests__/zosjobs/__unit__/search/__snapshots__/Search.definition.unit.test.ts.snap new file mode 100644 index 0000000000..d43e4640c9 --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__unit__/search/__snapshots__/Search.definition.unit.test.ts.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`zos-jobs search group definition should not have changed 1`] = ` +Object { + "aliases": Array [ + "sea", + ], + "description": "Search the spool output of a job.", + "name": "search", + "summary": "Search the spool output of a z/OS job", + "type": "group", +} +`; diff --git a/packages/cli/__tests__/zosjobs/__unit__/search/job/JobSearch.definition.unit.test.ts b/packages/cli/__tests__/zosjobs/__unit__/search/job/JobSearch.definition.unit.test.ts new file mode 100644 index 0000000000..f9facebeb1 --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__unit__/search/job/JobSearch.definition.unit.test.ts @@ -0,0 +1,22 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ICommandDefinition } from "@zowe/imperative"; + +describe("zos-jobs search job definition", () => { + it("should not have changed", () => { + const definition: ICommandDefinition + = require("../../../../../src/zosjobs/search/job/Job.definition").JobDefinition; + delete definition.handler; + expect(definition).toBeDefined(); + expect(definition).toMatchSnapshot(); + }); +}); diff --git a/packages/cli/__tests__/zosjobs/__unit__/search/job/JobSearch.handler.unit.test.ts b/packages/cli/__tests__/zosjobs/__unit__/search/job/JobSearch.handler.unit.test.ts new file mode 100644 index 0000000000..9b426a8201 --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__unit__/search/job/JobSearch.handler.unit.test.ts @@ -0,0 +1,68 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +jest.mock("@zowe/zos-jobs-for-zowe-sdk"); +import { IHandlerParameters, ImperativeError } from "@zowe/imperative"; +import { SearchJobs } from "@zowe/zos-jobs-for-zowe-sdk"; +import * as JobHandler from "../../../../../src/zosjobs/search/job/Job.handler"; +import * as JobDefinition from "../../../../../src/zosjobs/search/job/Job.definition"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; +import { mockHandlerParameters } from "@zowe/cli-test-utils"; + +process.env.FORCE_COLOR = "0"; + +const mockSearchData: string = "This job contains RC=0000"; + +// Mocked parameters for the unit tests +const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ + arguments: UNIT_TEST_ZOSMF_PROF_OPTS, + positionals: ["zos-jobs", "search", "job"], + definition: JobDefinition.JobDefinition +}); + +describe("search job handler tests", () => { + + afterEach(() => { + jest.resetAllMocks(); + }); + + it("should be able to search job spool", async () => { + SearchJobs.searchJobs = jest.fn(async (session, searchParms) => { + return mockSearchData; + }); + const handler = new JobHandler.default(); + const params = Object.assign({}, ...[DEFAULT_PARAMETERS]); + params.arguments.jobname = "j12345"; + params.arguments.searchString = "RC=0000"; + await handler.process(params); + expect(SearchJobs.searchJobs).toHaveBeenCalledTimes(1); + }); + + it("should be able respond with error message", async () => { + const failMessage = "You fail"; + let error; + SearchJobs.searchJobs = jest.fn(async (session, searchParms) => { + throw new ImperativeError({msg: failMessage}); + }); + const handler = new JobHandler.default(); + const params = Object.assign({}, ...[DEFAULT_PARAMETERS]); + params.arguments.jobname = "j12345"; + try { + await handler.process(params); + } catch (thrownError) { + error = thrownError; + } + expect(SearchJobs.searchJobs).toHaveBeenCalledTimes(1); + expect(error).toBeDefined(); + expect(error instanceof ImperativeError).toBe(true); + expect(error.message).toMatchSnapshot(); + }); +}); diff --git a/packages/cli/__tests__/zosjobs/__unit__/search/job/__snapshots__/JobSearch.definition.unit.test.ts.snap b/packages/cli/__tests__/zosjobs/__unit__/search/job/__snapshots__/JobSearch.definition.unit.test.ts.snap new file mode 100644 index 0000000000..476a1dc7db --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__unit__/search/job/__snapshots__/JobSearch.definition.unit.test.ts.snap @@ -0,0 +1,89 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`zos-jobs search job definition should not have changed 1`] = ` +Object { + "description": "Search the spool output of a job.", + "examples": Array [ + Object { + "description": "Search all jobs named USERJOB for the string \\"RC=0000\\"", + "options": "\\"USERJOB\\" --search-string \\"RC=0000\\"", + }, + Object { + "description": "Search all jobs that start with USER for the string \\"ENDED\\"", + "options": "\\"USER*\\" --search-string \\"ENDED\\"", + }, + Object { + "description": "Search all jobs named USERJOB for the string \\"COND CODE\\", with the options case sensitive and a search limit of 5", + "options": "\\"USERJOB\\" --search-string \\"COND CODE\\" --case-insensitive false --search-limit 5", + }, + ], + "name": "job", + "options": Array [ + Object { + "aliases": Array [ + "string", + ], + "defaultValue": undefined, + "description": "The string to search for in the spool output.", + "name": "search-string", + "required": false, + "type": "string", + }, + Object { + "aliases": Array [ + "regex", + ], + "defaultValue": undefined, + "description": "The regular expression to search for in the spool output.", + "name": "search-regex", + "required": false, + "type": "string", + }, + Object { + "aliases": Array [ + "ci", + ], + "defaultValue": true, + "description": "The search is case insensitive or not.", + "name": "case-insensitive", + "required": false, + "type": "boolean", + }, + Object { + "aliases": Array [ + "sl", + ], + "defaultValue": 100, + "description": "The maximum number of matching lines to return for an individual spool file.", + "name": "search-limit", + "required": false, + "type": "number", + }, + Object { + "aliases": Array [ + "fl", + ], + "defaultValue": 100, + "description": "The maximum number of spool files to search.", + "name": "file-limit", + "required": false, + "type": "number", + }, + ], + "positionals": Array [ + Object { + "description": "The job name to search. Wildcards are accepted for the job name. You can use, for example \\"USERJOB*\\" to search all jobs that start with USERJOB.", + "name": "jobname", + "required": true, + "type": "string", + }, + ], + "profile": Object { + "optional": Array [ + "zosmf", + ], + }, + "summary": "Search the spool output of a job.", + "type": "command", +} +`; diff --git a/packages/cli/__tests__/zosjobs/__unit__/search/job/__snapshots__/JobSearch.handler.unit.test.ts.snap b/packages/cli/__tests__/zosjobs/__unit__/search/job/__snapshots__/JobSearch.handler.unit.test.ts.snap new file mode 100644 index 0000000000..92a5efeb57 --- /dev/null +++ b/packages/cli/__tests__/zosjobs/__unit__/search/job/__snapshots__/JobSearch.handler.unit.test.ts.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`search job handler tests should be able respond with error message 1`] = `"You fail"`; + +exports[`search job handler tests should be able to search job spool 1`] = `"This job contains RC=0000"`; + +exports[`search job handler tests should be able to search job spool 2`] = `"This job contains RC=0000"`; diff --git a/packages/cli/__tests__/zosjobs/__unit__/submit/Submit.shared.handler.unit.test.ts b/packages/cli/__tests__/zosjobs/__unit__/submit/Submit.shared.handler.unit.test.ts index 11573cc424..a6ec8b0933 100644 --- a/packages/cli/__tests__/zosjobs/__unit__/submit/Submit.shared.handler.unit.test.ts +++ b/packages/cli/__tests__/zosjobs/__unit__/submit/Submit.shared.handler.unit.test.ts @@ -13,10 +13,7 @@ jest.mock("@zowe/zos-jobs-for-zowe-sdk"); import { MonitorJobs, SubmitJobs, ISubmitJobUSSParms, ISubmitJobParms } from "@zowe/zos-jobs-for-zowe-sdk"; import { IHandlerParameters, ImperativeError, IO } from "@zowe/imperative"; import * as SubmitDefinition from "../../../../src/zosjobs/submit/Submit.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; process.env.FORCE_COLOR = "0"; @@ -29,22 +26,19 @@ describe("submit shared handler", () => { DEFAULT_PARAMETERS = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-jobs", "submit", "data-set"], - definition: SubmitDefinition.SubmitDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: SubmitDefinition.SubmitDefinition }); USSFILE_PARAMETERS = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-jobs", "submit", "uss-file"], - definition: SubmitDefinition.SubmitDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: SubmitDefinition.SubmitDefinition }); LOCALFILE_PARAMETERS = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-jobs", "submit", "local-file"], - definition: SubmitDefinition.SubmitDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: SubmitDefinition.SubmitDefinition }); }); @@ -71,7 +65,34 @@ describe("submit shared handler", () => { expect(error).toBeDefined(); expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); + expect(error.message).toContain("Unable to determine the JCL source. Please contact support"); + }); + + it("should return any caught error, ie: ENOENT", async () => { + // Require the handler and create a new instance + const handlerReq = require("../../../../src/zosjobs/submit/Submit.shared.handler"); + const handler = new handlerReq.default(); + + // Vars populated by the mocked function + let error; + + // Local file doesn't exist and should be cause of failure + const theLocalFile: string = "fakefile"; + + const copy = Object.assign({}, LOCALFILE_PARAMETERS); + copy.arguments.localFile = theLocalFile; + try { + // Invoke the handler with a full set of mocked arguments and response functions + await handler.process(copy); + } catch (e) { + error = e; + } + + expect(error).toBeDefined(); + expect(error).toBeInstanceOf(ImperativeError); + expect(error.message).toContain("Node.js File System API error"); + expect(error.additionalDetails).toContain("ENOENT: no such file or directory, open"); + expect(error.additionalDetails).toContain("fakefile"); }); it("should not transform an error thrown by the submit JCL API", async () => { diff --git a/packages/cli/__tests__/zosjobs/__unit__/submit/__snapshots__/Submit.shared.handler.unit.test.ts.snap b/packages/cli/__tests__/zosjobs/__unit__/submit/__snapshots__/Submit.shared.handler.unit.test.ts.snap index 27d8f7e4a2..6836b4975d 100644 --- a/packages/cli/__tests__/zosjobs/__unit__/submit/__snapshots__/Submit.shared.handler.unit.test.ts.snap +++ b/packages/cli/__tests__/zosjobs/__unit__/submit/__snapshots__/Submit.shared.handler.unit.test.ts.snap @@ -1,7 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`submit shared handler error handling should detect if the JCL source type (data set, etc.) could not be determined 1`] = `"Internal submit error: Unable to determine the JCL source. Please contact support."`; - exports[`submit shared handler process method should submit JCL contained within a data-set if requested 1`] = ` Object { "fields": Array [ diff --git a/packages/cli/__tests__/zosjobs/__unit__/view/all-spool-content/AllSpoolContent.handler.unit.test.ts b/packages/cli/__tests__/zosjobs/__unit__/view/all-spool-content/AllSpoolContent.handler.unit.test.ts index c7cb2b4b33..432c0b22dd 100644 --- a/packages/cli/__tests__/zosjobs/__unit__/view/all-spool-content/AllSpoolContent.handler.unit.test.ts +++ b/packages/cli/__tests__/zosjobs/__unit__/view/all-spool-content/AllSpoolContent.handler.unit.test.ts @@ -16,7 +16,7 @@ import { GetJobsData } from "../../../__resources__/GetJobsData"; import { AllSpoolContentDefinition } from "../../../../../src/zosjobs/view/all-spool-content/AllSpoolContent.definition"; import * as fs from "fs"; import { ZosmfSession } from "@zowe/zosmf-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS, UNIT_TEST_PROFILES_ZOSMF } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; import * as AllSpoolContentHandler from "../../../../../src/zosjobs/view/all-spool-content/AllSpoolContent.handler"; @@ -27,8 +27,7 @@ const TEST_RESOURCES_DIR = __dirname + "/../../../__resources__"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-jobs", "view", "spool-file-by-id"], - definition: AllSpoolContentDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF, + definition: AllSpoolContentDefinition }); describe("zos-jobs view all-spool-content handler", () => { diff --git a/packages/cli/__tests__/zosjobs/__unit__/view/job/JobStatusByJobid.handler.unit.test.ts b/packages/cli/__tests__/zosjobs/__unit__/view/job/JobStatusByJobid.handler.unit.test.ts index 6e23fc4557..305b21e1ae 100644 --- a/packages/cli/__tests__/zosjobs/__unit__/view/job/JobStatusByJobid.handler.unit.test.ts +++ b/packages/cli/__tests__/zosjobs/__unit__/view/job/JobStatusByJobid.handler.unit.test.ts @@ -15,10 +15,7 @@ import { GetJobs } from "@zowe/zos-jobs-for-zowe-sdk"; import { GetJobsData } from "../../../__resources__/GetJobsData"; import * as JobStatusByJobidHandler from "../../../../../src/zosjobs/view/job-status-by-jobid/JobStatusByJobid.handler"; import * as JobStatusByJobidDefinition from "../../../../../src/zosjobs/view/job-status-by-jobid/JobStatusByJobid.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; process.env.FORCE_COLOR = "0"; @@ -27,8 +24,7 @@ process.env.FORCE_COLOR = "0"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-jobs", "view", "job"], - definition: JobStatusByJobidDefinition.JobStatusByJobidDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: JobStatusByJobidDefinition.JobStatusByJobidDefinition }); describe("view job-status-by-jobid handler tests", () => { diff --git a/packages/cli/__tests__/zosjobs/__unit__/view/spool-file-by-id/SpoolFileById.handler.unit.test.ts b/packages/cli/__tests__/zosjobs/__unit__/view/spool-file-by-id/SpoolFileById.handler.unit.test.ts index 094cc6e9ed..6d6582727f 100644 --- a/packages/cli/__tests__/zosjobs/__unit__/view/spool-file-by-id/SpoolFileById.handler.unit.test.ts +++ b/packages/cli/__tests__/zosjobs/__unit__/view/spool-file-by-id/SpoolFileById.handler.unit.test.ts @@ -17,7 +17,7 @@ import { SpoolFilesByJobidDefinition } from "../../../../../src/zosjobs/list/spo import * as SpoolFileByIdHandler from "../../../../../src/zosjobs/view/spool-file-by-id/SpoolFileById.handler"; import * as fs from "fs"; import { ZosmfSession } from "@zowe/zosmf-for-zowe-sdk"; -import { UNIT_TEST_ZOSMF_PROF_OPTS, UNIT_TEST_PROFILES_ZOSMF } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; import { cloneDeep } from "lodash"; @@ -28,8 +28,7 @@ const TEST_RESOURCES_DIR = __dirname + "/../../../__resources__"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-jobs", "view", "spool-file-by-id"], - definition: SpoolFilesByJobidDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: SpoolFilesByJobidDefinition }); describe("zos-jobs view spool-file-by-id handler", () => { diff --git a/packages/cli/__tests__/zoslogs/__unit__/list/logs/Logs.handler.unit.test.ts b/packages/cli/__tests__/zoslogs/__unit__/list/logs/Logs.handler.unit.test.ts index 621d1be7e6..5fb4912fc3 100644 --- a/packages/cli/__tests__/zoslogs/__unit__/list/logs/Logs.handler.unit.test.ts +++ b/packages/cli/__tests__/zoslogs/__unit__/list/logs/Logs.handler.unit.test.ts @@ -15,10 +15,7 @@ import { IHandlerParameters, ImperativeError, Session, Imperative } from "@zowe/ import * as LogsHandler from "../../../../../src/zoslogs/list/logs/Logs.handler"; import * as LogsDefinition from "../../../../../src/zoslogs/list/logs/Logs.definition"; import { GetZosLog, IZosLogParms } from "@zowe/zos-logs-for-zowe-sdk"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; process.env.FORCE_COLOR = "0"; @@ -29,8 +26,7 @@ const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ ...UNIT_TEST_ZOSMF_PROF_OPTS }, positionals: ["zos-logs", "list", "logs"], - definition: LogsDefinition.LogsDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: LogsDefinition.LogsDefinition }); describe("get logs handler tests", () => { @@ -80,7 +76,7 @@ describe("get logs handler tests", () => { params.arguments.startTime = "1626912000000"; params.arguments.range = "5m"; params.arguments.direction = "backward"; - Imperative.console.info(params.arguments); + Imperative.console.info(JSON.stringify(params.arguments)); await handler.process(params); expect(GetZosLog.getZosLog).toHaveBeenCalledTimes(1); expect(GetZosLog.getZosLog).toHaveBeenCalledWith(passedSession, passedParms); diff --git a/packages/cli/__tests__/zosmf/__unit__/check/__snapshots__/Check.definition.unit.test.ts.snap b/packages/cli/__tests__/zosmf/__unit__/check/__snapshots__/Check.definition.unit.test.ts.snap index 5fc3fa2e05..841d78380f 100644 --- a/packages/cli/__tests__/zosmf/__unit__/check/__snapshots__/Check.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosmf/__unit__/check/__snapshots__/Check.definition.unit.test.ts.snap @@ -2,8 +2,9 @@ exports[`zosmf check group definition should have the right command content 1`] = ` Object { - "description": "Confirm that z/OSMF is running on a specified system and gather information about the z/OSMF server for diagnostic purposes. ", + "description": "Confirm that z/OSMF is running on a specified system and gather information about the z/OSMF server for diagnostic purposes.", "name": "check", + "summary": "Check z/OSMF status on a specified system", "type": "group", } `; diff --git a/packages/cli/__tests__/zosmf/__unit__/check/status/Status.handler.unit.test.ts b/packages/cli/__tests__/zosmf/__unit__/check/status/Status.handler.unit.test.ts index 7f308537e4..e3800ce919 100644 --- a/packages/cli/__tests__/zosmf/__unit__/check/status/Status.handler.unit.test.ts +++ b/packages/cli/__tests__/zosmf/__unit__/check/status/Status.handler.unit.test.ts @@ -14,17 +14,13 @@ import { CheckStatus } from "@zowe/zosmf-for-zowe-sdk"; import { ICommandHandler, IHandlerParameters } from "@zowe/imperative"; import CmdHandler from "../../../../../src/zosmf/check/status/Status.handler"; import * as cmdDef from "../../../../../src/zosmf/check/status/Status.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; const goodCmdParms: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zosmf", "check", "status"], - definition: cmdDef.StatusDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: cmdDef.StatusDefinition }); let checkStatHandler: ICommandHandler = null; @@ -56,7 +52,7 @@ describe("check status behavior", () => { parmsToUse.response.console.log = jest.fn((logs) => { expect(logs).toMatchSnapshot(); expect(logs).toContain("successfully connected to z/OSMF"); - }); + }) as any; await checkStatHandler.process(parmsToUse); expect(CheckStatus.getZosmfInfo).toHaveBeenCalledTimes(1); @@ -83,7 +79,7 @@ describe("check status behavior", () => { parmsToUse.response.console.error = jest.fn((errors) => { expect(errors).toMatchSnapshot(); expect(errors).toContain("Mock GetInfo Error"); - }); + }) as any; let error; try { diff --git a/packages/cli/__tests__/zosmf/__unit__/check/status/__snapshots__/Status.definition.unit.test.ts.snap b/packages/cli/__tests__/zosmf/__unit__/check/status/__snapshots__/Status.definition.unit.test.ts.snap index 79bc1b5523..e693e39a2b 100644 --- a/packages/cli/__tests__/zosmf/__unit__/check/status/__snapshots__/Status.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosmf/__unit__/check/status/__snapshots__/Status.definition.unit.test.ts.snap @@ -111,6 +111,7 @@ Object { "zosmf", ], }, + "summary": "Check z/OSMF status on a specified system", "type": "command", } `; diff --git a/packages/cli/__tests__/zosmf/__unit__/list/__snapshots__/List.definition.unit.test.ts.snap b/packages/cli/__tests__/zosmf/__unit__/list/__snapshots__/List.definition.unit.test.ts.snap index cd0df77044..25b6a4bc04 100644 --- a/packages/cli/__tests__/zosmf/__unit__/list/__snapshots__/List.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosmf/__unit__/list/__snapshots__/List.definition.unit.test.ts.snap @@ -4,6 +4,7 @@ exports[`zosmf list group definition should have the right command content 1`] = Object { "description": "Obtain a list of systems that are defined to a z/OSMF instance.", "name": "list", + "summary": "Obtain a list of systems that are defined to a z/OSMF instance", "type": "group", } `; diff --git a/packages/cli/__tests__/zosmf/__unit__/list/systems/Systems.handler.unit.test.ts b/packages/cli/__tests__/zosmf/__unit__/list/systems/Systems.handler.unit.test.ts index bf37ea0a8e..fa2c8e5a32 100644 --- a/packages/cli/__tests__/zosmf/__unit__/list/systems/Systems.handler.unit.test.ts +++ b/packages/cli/__tests__/zosmf/__unit__/list/systems/Systems.handler.unit.test.ts @@ -15,17 +15,13 @@ import { ListDefinedSystems } from "@zowe/zosmf-for-zowe-sdk"; import { ICommandHandler, IHandlerParameters } from "@zowe/imperative"; import CmdHandler from "../../../../../src/zosmf/list/systems/Systems.handler"; import * as cmdDef from "../../../../../src/zosmf/list/systems/Systems.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; const goodCmdParms: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zosmf", "check", "status"], - definition: cmdDef.SystemsDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: cmdDef.SystemsDefinition }); let listSystemsHandler: ICommandHandler = null; @@ -59,7 +55,7 @@ describe("List systems behavior", () => { parmsToUse.response.console.log = jest.fn((logs) => { expect(logs).toMatchSnapshot(); expect(logs).toContain("Number of retreived system definitions:"); - }); + }) as any; await listSystemsHandler.process(parmsToUse); expect(ListDefinedSystems.listDefinedSystems).toHaveBeenCalledTimes(1); @@ -89,7 +85,7 @@ describe("List systems behavior", () => { parmsToUse.response.console.error = jest.fn((errors) => { expect(errors).toMatchSnapshot(); expect(errors).toContain("Mock GetInfo Error"); - }); + }) as any; let error; try { diff --git a/packages/cli/__tests__/zosmf/__unit__/list/systems/__snapshots__/Systems.definition.unit.test.ts.snap b/packages/cli/__tests__/zosmf/__unit__/list/systems/__snapshots__/Systems.definition.unit.test.ts.snap index f2d317d9ed..e295912cbe 100644 --- a/packages/cli/__tests__/zosmf/__unit__/list/systems/__snapshots__/Systems.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosmf/__unit__/list/systems/__snapshots__/Systems.definition.unit.test.ts.snap @@ -111,6 +111,7 @@ Object { "zosmf", ], }, + "summary": "Obtain a list of systems that are defined to a z/OSMF instance", "type": "command", } `; diff --git a/packages/cli/__tests__/zostso/__integration__/root/__snapshots__/cli.zos-tso.integration.test.ts.snap b/packages/cli/__tests__/zostso/__integration__/root/__snapshots__/cli.zos-tso.integration.test.ts.snap index 01f7cf6730..be8a0738b8 100644 --- a/packages/cli/__tests__/zostso/__integration__/root/__snapshots__/cli.zos-tso.integration.test.ts.snap +++ b/packages/cli/__tests__/zostso/__integration__/root/__snapshots__/cli.zos-tso.integration.test.ts.snap @@ -51,29 +51,3 @@ exports[`zos-tso should display the help 1`] = ` \\"data\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Issue TSO commands and interact with TSO address spaces.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-tso \\\\n\\\\n Where is one of the following:\\\\n\\\\n GROUPS\\\\n ------\\\\n\\\\n issue Issue TSO commands \\\\n ping Ping a TSO address space \\\\n send Send data to TSO \\\\n start | st Start TSO/E address space\\\\n stop | sp Stop TSO/E address space \\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" }" `; - -exports[`zos-tso should fail with invalid option 1`] = ` -"Command Error: -Unknown arguments: not-valid-option, notValidOption -Command failed due to improper syntax -Did you mean: zos-tso start? - -Command entered: \\"zos-tso --not-valid-option\\" -Use \\"zowe zos-tso --help\\" to view groups, commands, and options. -Error Details: -Unknown arguments: not-valid-option, notValidOption -" -`; - -exports[`zos-tso should fail with invalid parameter 1`] = ` -"Command Error: -Unknown argument: examine -Command failed due to improper syntax -Did you mean: zos-tso ping? - -Command entered: \\"zos-tso examine\\" -Use \\"zowe zos-tso --help\\" to view groups, commands, and options. -Error Details: -Unknown argument: examine -" -`; diff --git a/packages/cli/__tests__/zostso/__integration__/root/cli.zos-tso.integration.test.ts b/packages/cli/__tests__/zostso/__integration__/root/cli.zos-tso.integration.test.ts index 0d96537777..75a1fb62dc 100644 --- a/packages/cli/__tests__/zostso/__integration__/root/cli.zos-tso.integration.test.ts +++ b/packages/cli/__tests__/zostso/__integration__/root/cli.zos-tso.integration.test.ts @@ -36,14 +36,22 @@ describe("zos-tso", () => { it("should fail with invalid parameter", async () => { const response = runCliScript(__dirname + "/__scripts__/invalid_command.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); - expect(response.stderr.toString()).toMatchSnapshot(); expect(response.stdout.toString()).toBe(""); + expect(response.stderr.toString()).toContain('Unknown argument: examine'); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Did you mean: zos-tso ping'); + expect(response.stderr.toString()).toContain('Command entered: "zos-tso examine"'); + expect(response.stderr.toString()).toContain('Use "zowe zos-tso --help" to view groups, commands, and options.'); }); it("should fail with invalid option", async () => { const response = runCliScript(__dirname + "/__scripts__/invalid_option.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); - expect(response.stderr.toString()).toMatchSnapshot(); expect(response.stdout.toString()).toBe(""); + expect(response.stderr.toString()).toContain('Unknown arguments: not-valid-option, notValidOption'); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Did you mean: zos-tso start'); + expect(response.stderr.toString()).toContain('Command entered: "zos-tso --not-valid-option"'); + expect(response.stderr.toString()).toContain('Use "zowe zos-tso --help" to view groups, commands, and options.'); }); }); diff --git a/packages/cli/__tests__/zostso/__integration__/start/__scripts__/start_invalid_option.sh b/packages/cli/__tests__/zostso/__integration__/start/__scripts__/start_invalid_option.sh index e80cd5736b..21d37b21e2 100755 --- a/packages/cli/__tests__/zostso/__integration__/start/__scripts__/start_invalid_option.sh +++ b/packages/cli/__tests__/zostso/__integration__/start/__scripts__/start_invalid_option.sh @@ -1,6 +1,6 @@ #!/bin/bash set -e -echo "================Z/OS CONSOLE INVALID PARAMETERS===============" +echo "================Z/OS CONSOLE INVALID OPTION===============" zowe zos-tso start --foo-bar exit $? \ No newline at end of file diff --git a/packages/cli/__tests__/zostso/__integration__/start/__snapshots__/cli.zos-tso.start.integration.test.ts.snap b/packages/cli/__tests__/zostso/__integration__/start/__snapshots__/cli.zos-tso.start.integration.test.ts.snap index b2b7db97d1..1f08304a7a 100644 --- a/packages/cli/__tests__/zostso/__integration__/start/__snapshots__/cli.zos-tso.start.integration.test.ts.snap +++ b/packages/cli/__tests__/zostso/__integration__/start/__snapshots__/cli.zos-tso.start.integration.test.ts.snap @@ -17,9 +17,7 @@ exports[`zos-tso start should display the help 1`] = ` COMMANDS -------- - address-space | as Start a TSO address space, from which you will receive a - token (a.k.a 'servlet-key') for further address space - interaction (e.g. termination). + address-space | as Start a TSO address space GLOBAL OPTIONS -------------- @@ -44,46 +42,8 @@ exports[`zos-tso start should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: start.\\", - \\"stdout\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Start TSO/E address space.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-tso start \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n address-space | as Start a TSO address space, from which you will receive a\\\\n token (a.k.a 'servlet-key') for further address space \\\\n interaction (e.g. termination). \\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Start TSO/E address space.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-tso start \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n address-space | as Start a TSO address space\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Start TSO/E address space.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-tso start \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n address-space | as Start a TSO address space, from which you will receive a\\\\n token (a.k.a 'servlet-key') for further address space \\\\n interaction (e.g. termination). \\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" + \\"data\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Start TSO/E address space.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-tso start \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n address-space | as Start a TSO address space\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" }" `; - -exports[`zos-tso start should fail with invalid option 1`] = ` -"Command Error: -Unknown arguments: foo-bar, fooBar -Command failed due to improper syntax -Did you mean: zos-tso start as? - -Command entered: \\"zos-tso start --foo-bar\\" -Available commands are \\"address-space\\". -Use \\"zowe zos-tso start --help\\" to view groups, commands, and options. -Error Details: -Unknown arguments: foo-bar, fooBar -" -`; - -exports[`zos-tso start should fail with invalid option 2`] = ` -"================Z/OS CONSOLE INVALID PARAMETERS=============== -" -`; - -exports[`zos-tso start should fail with invalid parameter 1`] = ` -"Command Error: -Unknown argument: foobar -Command failed due to improper syntax -Did you mean: zos-tso start as? - -Command entered: \\"zos-tso start foobar\\" -Available commands are \\"address-space\\". -Use \\"zowe zos-tso start --help\\" to view groups, commands, and options. -Error Details: -Unknown argument: foobar -" -`; - -exports[`zos-tso start should fail with invalid parameter 2`] = ` -"================Z/OS CONSOLE INVALID PARAMETERS=============== -" -`; diff --git a/packages/cli/__tests__/zostso/__integration__/start/cli.zos-tso.start.integration.test.ts b/packages/cli/__tests__/zostso/__integration__/start/cli.zos-tso.start.integration.test.ts index c543cecd59..c0a244761a 100644 --- a/packages/cli/__tests__/zostso/__integration__/start/cli.zos-tso.start.integration.test.ts +++ b/packages/cli/__tests__/zostso/__integration__/start/cli.zos-tso.start.integration.test.ts @@ -36,15 +36,26 @@ describe("zos-tso start", () => { it("should fail with invalid parameter", async () => { const response = runCliScript(__dirname + "/__scripts__/start_invalid_parameter.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); - expect(response.stderr.toString()).toMatchSnapshot(); - expect(response.stdout.toString()).toMatchSnapshot(); + expect(response.stdout.toString()).toContain('================Z/OS CONSOLE INVALID PARAMETERS==============='); + expect(response.stderr.toString()).toContain('Unknown argument: foobar'); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Did you mean: zos-tso start'); + expect(response.stderr.toString()).toContain('Command entered: "zos-tso start foobar"'); + expect(response.stderr.toString()).toContain('Available commands are "address-space".'); + expect(response.stderr.toString()).toContain('Use "zowe zos-tso start --help" to view groups, commands, and options.'); + expect(response.stderr.toString()).toContain('Error: Unknown argument: foobar'); }); it("should fail with invalid option", async () => { const response = runCliScript(__dirname + "/__scripts__/start_invalid_option.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); - expect(response.stderr.toString()).toMatchSnapshot(); - expect(response.stdout.toString()).toMatchSnapshot(); + expect(response.stdout.toString()).toContain('================Z/OS CONSOLE INVALID OPTION==============='); + expect(response.stderr.toString()).toContain('Unknown arguments: foo-bar, fooBar'); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Command entered: "zos-tso start --foo-bar"'); + expect(response.stderr.toString()).toContain('Available commands are "address-space".'); + expect(response.stderr.toString()).toContain('Use "zowe zos-tso start --help" to view groups, commands, and options.'); + expect(response.stderr.toString()).toContain('Error: Unknown arguments: foo-bar, fooBar'); }); }); diff --git a/packages/cli/__tests__/zostso/__integration__/stop/__scripts__/stop_invalid_option.sh b/packages/cli/__tests__/zostso/__integration__/stop/__scripts__/stop_invalid_option.sh index 8c24271806..d71c1545c2 100755 --- a/packages/cli/__tests__/zostso/__integration__/stop/__scripts__/stop_invalid_option.sh +++ b/packages/cli/__tests__/zostso/__integration__/stop/__scripts__/stop_invalid_option.sh @@ -1,6 +1,6 @@ #!/bin/bash set -e -echo "================Z/OS CONSOLE INVALID PARAMETERS===============" -zowe zos-tso start as --foo-bar +echo "================Z/OS CONSOLE INVALID OPTION===============" +zowe zos-tso stop as --foo-bar exit $? \ No newline at end of file diff --git a/packages/cli/__tests__/zostso/__integration__/stop/__snapshots__/cli.zos-tso.stop.integration.test.ts.snap b/packages/cli/__tests__/zostso/__integration__/stop/__snapshots__/cli.zos-tso.stop.integration.test.ts.snap index f5b69e2d3c..16e1198999 100644 --- a/packages/cli/__tests__/zostso/__integration__/stop/__snapshots__/cli.zos-tso.stop.integration.test.ts.snap +++ b/packages/cli/__tests__/zostso/__integration__/stop/__snapshots__/cli.zos-tso.stop.integration.test.ts.snap @@ -17,8 +17,7 @@ exports[`zos-tso stop should display the help 1`] = ` COMMANDS -------- - address-space | as Stop a TSO address space, from which you previously started - and received a token (a.k.a 'servlet-key'). + address-space | as Stop a TSO address space GLOBAL OPTIONS -------------- @@ -43,44 +42,8 @@ exports[`zos-tso stop should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: stop.\\", - \\"stdout\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Stop TSO/E address space.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-tso stop \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n address-space | as Stop a TSO address space, from which you previously started\\\\n and received a token (a.k.a 'servlet-key'). \\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Stop TSO/E address space.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-tso stop \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n address-space | as Stop a TSO address space\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Stop TSO/E address space.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-tso stop \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n address-space | as Stop a TSO address space, from which you previously started\\\\n and received a token (a.k.a 'servlet-key'). \\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" + \\"data\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Stop TSO/E address space.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-tso stop \\\\n\\\\n Where is one of the following:\\\\n\\\\n COMMANDS\\\\n --------\\\\n\\\\n address-space | as Stop a TSO address space\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --help-examples (boolean)\\\\n\\\\n Display examples for all the commands in a group\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" }" `; - -exports[`zos-tso stop should fail with invalid option 1`] = ` -"Command Error: -Unknown arguments: foo-bar, fooBar -Command failed due to improper syntax -Command entered: \\"zos-tso start as --foo-bar\\" -Available commands are \\"address-space\\". -Use \\"zowe zos-tso start --help\\" to view groups, commands, and options. -Error Details: -Unknown arguments: foo-bar, fooBar -" -`; - -exports[`zos-tso stop should fail with invalid option 2`] = ` -"================Z/OS CONSOLE INVALID PARAMETERS=============== -" -`; - -exports[`zos-tso stop should fail with invalid parameter 1`] = ` -"Command Error: -Unknown argument: foobar -Command failed due to improper syntax -Did you mean: zos-tso stop as? - -Command entered: \\"zos-tso stop foobar\\" -Available commands are \\"address-space\\". -Use \\"zowe zos-tso stop --help\\" to view groups, commands, and options. -Error Details: -Unknown argument: foobar -" -`; - -exports[`zos-tso stop should fail with invalid parameter 2`] = ` -"================Z/OS CONSOLE INVALID PARAMETERS=============== -" -`; diff --git a/packages/cli/__tests__/zostso/__integration__/stop/cli.zos-tso.stop.integration.test.ts b/packages/cli/__tests__/zostso/__integration__/stop/cli.zos-tso.stop.integration.test.ts index 1de660fbfb..34bd66ab4e 100644 --- a/packages/cli/__tests__/zostso/__integration__/stop/cli.zos-tso.stop.integration.test.ts +++ b/packages/cli/__tests__/zostso/__integration__/stop/cli.zos-tso.stop.integration.test.ts @@ -36,14 +36,25 @@ describe("zos-tso stop", () => { it("should fail with invalid parameter", async () => { const response = runCliScript(__dirname + "/__scripts__/stop_invalid_parameter.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); - expect(response.stderr.toString()).toMatchSnapshot(); - expect(response.stdout.toString()).toMatchSnapshot(); + expect(response.stdout.toString()).toContain('================Z/OS CONSOLE INVALID PARAMETERS==============='); + expect(response.stderr.toString()).toContain('Unknown argument: foobar'); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Did you mean: zos-tso stop'); + expect(response.stderr.toString()).toContain('Command entered: "zos-tso stop foobar"'); + expect(response.stderr.toString()).toContain('Available commands are "address-space".'); + expect(response.stderr.toString()).toContain('Use "zowe zos-tso stop --help" to view groups, commands, and options.'); + expect(response.stderr.toString()).toContain('Error: Unknown argument: foobar'); }); it("should fail with invalid option", async () => { const response = runCliScript(__dirname + "/__scripts__/stop_invalid_option.sh", TEST_ENVIRONMENT); expect(response.status).toBe(1); - expect(response.stderr.toString()).toMatchSnapshot(); - expect(response.stdout.toString()).toMatchSnapshot(); + expect(response.stdout.toString()).toContain('================Z/OS CONSOLE INVALID OPTION==============='); + expect(response.stderr.toString()).toContain('Unknown arguments: foo-bar, fooBar'); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Command entered: "zos-tso stop as --foo-bar"'); + expect(response.stderr.toString()).toContain('Available commands are "address-space".'); + expect(response.stderr.toString()).toContain('Use "zowe zos-tso stop --help" to view groups, commands, and options.'); + expect(response.stderr.toString()).toContain('Error: Unknown arguments: foo-bar, fooBar'); }); }); diff --git a/packages/cli/__tests__/zostso/__system__/ping/__snapshots__/cli.zos-tso.ping.address-space.system.test.ts.snap b/packages/cli/__tests__/zostso/__system__/ping/__snapshots__/cli.zos-tso.ping.address-space.system.test.ts.snap index 0ce860177a..24c7d70612 100644 --- a/packages/cli/__tests__/zostso/__system__/ping/__snapshots__/cli.zos-tso.ping.address-space.system.test.ts.snap +++ b/packages/cli/__tests__/zostso/__system__/ping/__snapshots__/cli.zos-tso.ping.address-space.system.test.ts.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`zos-tso ping address-space should throw an error if provided address space is inactive 1`] = ` -"Command Error: +"Unable to perform this operation due to the following problem. Expect Error: IZUG1126E: z/OSMF cannot correlate the request for key \\"BadKey\\" with an active z/OS application session. " `; diff --git a/packages/cli/__tests__/zostso/__system__/stop/__snapshots__/cli.zos-tso.stop.address-space.system.test.ts.snap b/packages/cli/__tests__/zostso/__system__/stop/__snapshots__/cli.zos-tso.stop.address-space.system.test.ts.snap deleted file mode 100644 index 48674f0023..0000000000 --- a/packages/cli/__tests__/zostso/__system__/stop/__snapshots__/cli.zos-tso.stop.address-space.system.test.ts.snap +++ /dev/null @@ -1,13 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`zos-tso start address-space should throw an error if provided address space is inactive 1`] = ` -"Command Error: -Expect Error: IZUG1126E: z/OSMF cannot correlate the request for key \\"ZOSMFAD-55-aaakaaac\\" with an active z/OS application session. -" -`; - -exports[`zos-tso start address-space should throw an error if servlet key parameter is not provided 1`] = ` -"Command Error: -Expect Error: IZUG1126E: z/OSMF cannot correlate the request for key \\"ZOSMFAD-55-aaakaaac\\" with an active z/OS application session. -" -`; diff --git a/packages/cli/__tests__/zostso/__system__/stop/__snapshots__/cli.zos-tso.stop.system.test.ts.snap b/packages/cli/__tests__/zostso/__system__/stop/__snapshots__/cli.zos-tso.stop.system.test.ts.snap index 21484fcd84..aab1477817 100644 --- a/packages/cli/__tests__/zostso/__system__/stop/__snapshots__/cli.zos-tso.stop.system.test.ts.snap +++ b/packages/cli/__tests__/zostso/__system__/stop/__snapshots__/cli.zos-tso.stop.system.test.ts.snap @@ -1,13 +1,17 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`zos-tso stop should fail with invalid option 1`] = ` -"Command Error: +"Unable to perform this operation due to the following problem. Unknown arguments: foo-bar, fooBar Command failed due to improper syntax Command entered: \\"zos-tso start as --foo-bar\\" Available commands are \\"address-space\\". Use \\"zowe zos-tso start --help\\" to view groups, commands, and options. -Error Details: + +Response From Service +Error: Unknown arguments: foo-bar, fooBar + +Diagnostic Information Unknown arguments: foo-bar, fooBar " `; @@ -18,7 +22,7 @@ exports[`zos-tso stop should fail with invalid option 2`] = ` `; exports[`zos-tso stop should fail with invalid parameter 1`] = ` -"Command Error: +"Unable to perform this operation due to the following problem. Unknown argument: foobar Command failed due to improper syntax Did you mean: zos-tso stop as? @@ -26,7 +30,11 @@ Did you mean: zos-tso stop as? Command entered: \\"zos-tso stop foobar\\" Available commands are \\"address-space\\". Use \\"zowe zos-tso stop --help\\" to view groups, commands, and options. -Error Details: + +Response From Service +Error: Unknown argument: foobar + +Diagnostic Information Unknown argument: foobar " `; diff --git a/packages/cli/__tests__/zostso/__system__/stop/cli.zos-tso.stop.address-space.system.test.ts b/packages/cli/__tests__/zostso/__system__/stop/cli.zos-tso.stop.address-space.system.test.ts index 0a70be9700..f3b3167211 100644 --- a/packages/cli/__tests__/zostso/__system__/stop/cli.zos-tso.stop.address-space.system.test.ts +++ b/packages/cli/__tests__/zostso/__system__/stop/cli.zos-tso.stop.address-space.system.test.ts @@ -32,16 +32,18 @@ describe("zos-tso start address-space", () => { it("should throw an error if servlet key parameter is not provided", async () => { const response = runCliScript(__dirname + "/__scripts__/address-space/as_error_stop.sh", TEST_ENVIRONMENT); - expect(response.status).toBe(1); expect(response.stdout.toString()).toBe(""); - expect(response.stderr.toString()).toMatchSnapshot(); + expect(response.stderr.toString()).toContain('IZUG1126E: z/OSMF cannot correlate the request for ' + + 'key "ZOSMFAD-55-aaakaaac" with an active z/OS application session'); + expect(response.status).toBe(1); }); it("should throw an error if provided address space is inactive", async () => { const response = runCliScript(__dirname + "/__scripts__/address-space/as_error_stop.sh", TEST_ENVIRONMENT); - expect(response.status).toBe(1); expect(response.stdout.toString()).toBe(""); - expect(response.stderr.toString()).toMatchSnapshot(); + expect(response.stderr.toString()).toContain('IZUG1126E: z/OSMF cannot correlate the request for ' + + 'key "ZOSMFAD-55-aaakaaac" with an active z/OS application session'); + expect(response.status).toBe(1); }); it("should successfully issue the command", async () => { diff --git a/packages/cli/__tests__/zostso/__unit__/issue/command/Command.handler.unit.test.ts b/packages/cli/__tests__/zostso/__unit__/issue/command/Command.handler.unit.test.ts index 6bf449c70d..7d82689383 100644 --- a/packages/cli/__tests__/zostso/__unit__/issue/command/Command.handler.unit.test.ts +++ b/packages/cli/__tests__/zostso/__unit__/issue/command/Command.handler.unit.test.ts @@ -15,11 +15,7 @@ import { IHandlerParameters, ImperativeError } from "@zowe/imperative"; import * as Command from "../../../../../src/zostso/issue/command/Command.handler"; import { CommandDefinition } from "../../../../../src/zostso/issue/command/Command.definition"; import { StartTsoData } from "../../../__resources__/StartTsoData"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF_TSO, - UNIT_TEST_TSO_PROF_OPTS -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS, UNIT_TEST_TSO_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ @@ -28,8 +24,7 @@ const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ ...UNIT_TEST_TSO_PROF_OPTS }, positionals: ["zos-tso", "issue", "address-space"], - definition: CommandDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF_TSO + definition: CommandDefinition }); describe("issue command handler tests", () => { diff --git a/packages/cli/__tests__/zostso/__unit__/ping/address-space/AddressSpace.handler.unit.test.ts b/packages/cli/__tests__/zostso/__unit__/ping/address-space/AddressSpace.handler.unit.test.ts index d8a0b0aa38..1c63e55c73 100644 --- a/packages/cli/__tests__/zostso/__unit__/ping/address-space/AddressSpace.handler.unit.test.ts +++ b/packages/cli/__tests__/zostso/__unit__/ping/address-space/AddressSpace.handler.unit.test.ts @@ -16,17 +16,13 @@ import { PingTso } from "@zowe/zos-tso-for-zowe-sdk"; import { IHandlerParameters, ImperativeError } from "@zowe/imperative"; import * as PingAddressSpaceHandler from "../../../../../src/zostso/ping/address_space/PingAddressSpace.handler"; import { PingAddressSpaceCommandDefinition } from "../../../../../src/zostso/ping/address_space/PingAddressSpace.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-tso", "ping", "address-space"], - definition: PingAddressSpaceCommandDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: PingAddressSpaceCommandDefinition }); describe("ping address-space handler tests", () => { diff --git a/packages/cli/__tests__/zostso/__unit__/send/address-space/AddressSpace.handler.unit.test.ts b/packages/cli/__tests__/zostso/__unit__/send/address-space/AddressSpace.handler.unit.test.ts index c439ca7aee..584e3ab655 100644 --- a/packages/cli/__tests__/zostso/__unit__/send/address-space/AddressSpace.handler.unit.test.ts +++ b/packages/cli/__tests__/zostso/__unit__/send/address-space/AddressSpace.handler.unit.test.ts @@ -16,17 +16,13 @@ import { SendTso } from "@zowe/zos-tso-for-zowe-sdk"; import { IHandlerParameters, ImperativeError } from "@zowe/imperative"; import * as SendToAddressSpace from "../../../../../src/zostso/send/address_space/SendToAddressSpace.handler"; import { SendToAddressSpaceCommandDefinition } from "../../../../../src/zostso/send/address_space/SendToAddressSpace.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-tso", "send", "address-space"], - definition: SendToAddressSpaceCommandDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: SendToAddressSpaceCommandDefinition }); describe("send address-space handler tests", () => { diff --git a/packages/cli/__tests__/zostso/__unit__/start/address-space/AddressSpace.handler.unit.test.ts b/packages/cli/__tests__/zostso/__unit__/start/address-space/AddressSpace.handler.unit.test.ts index 5bd864a64f..3b9411ee08 100644 --- a/packages/cli/__tests__/zostso/__unit__/start/address-space/AddressSpace.handler.unit.test.ts +++ b/packages/cli/__tests__/zostso/__unit__/start/address-space/AddressSpace.handler.unit.test.ts @@ -11,23 +11,12 @@ import { StartTso } from "@zowe/zos-tso-for-zowe-sdk"; import { StartTsoData } from "../../../__resources__/StartTsoData"; -import { CommandProfiles, IHandlerParameters, ImperativeError, IProfile } from "@zowe/imperative"; +import { IHandlerParameters, ImperativeError } from "@zowe/imperative"; import * as AddressSpaceHandler from "../../../../../src/zostso/start/address-space/AddressSpace.handler"; import * as AddressSpaceDefinition from "../../../../../src/zostso/start/address-space/AddressSpace.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; -const PROFILE_MAP = new Map(); -PROFILE_MAP.set( - "zosmf", [{ - name: "zosmf", - type: "zosmf", - ...UNIT_TEST_ZOSMF_PROF_OPTS - }] -); - const TSO_PROF_OPTS = { logonProcedure: "IZUFPROC", characterSet: "697", @@ -38,21 +27,10 @@ const TSO_PROF_OPTS = { account: "DEFAULT" }; -PROFILE_MAP.set( - "tso", [{ - name: "tso", - type: "tso", - ...TSO_PROF_OPTS - }] -); - -const PROFILES: CommandProfiles = new CommandProfiles(PROFILE_MAP); - const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-tso", "start", "address-space"], - definition: AddressSpaceDefinition.AddressSpaceDefinition, - profiles: PROFILES + definition: AddressSpaceDefinition.AddressSpaceDefinition }); describe("start address-space handler tests", () => { diff --git a/packages/cli/__tests__/zostso/__unit__/start/address-space/__snapshots__/AddressSpace.definition.unit.test.ts.snap b/packages/cli/__tests__/zostso/__unit__/start/address-space/__snapshots__/AddressSpace.definition.unit.test.ts.snap index fbe886bc40..84fa3ed18b 100644 --- a/packages/cli/__tests__/zostso/__unit__/start/address-space/__snapshots__/AddressSpace.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zostso/__unit__/start/address-space/__snapshots__/AddressSpace.definition.unit.test.ts.snap @@ -104,6 +104,7 @@ Object { "tso", ], }, + "summary": "Start a TSO address space", "type": "command", } `; diff --git a/packages/cli/__tests__/zostso/__unit__/stop/address-space/AddressSpace.handler.unit.test.ts b/packages/cli/__tests__/zostso/__unit__/stop/address-space/AddressSpace.handler.unit.test.ts index 978f739e01..80c78c1acf 100644 --- a/packages/cli/__tests__/zostso/__unit__/stop/address-space/AddressSpace.handler.unit.test.ts +++ b/packages/cli/__tests__/zostso/__unit__/stop/address-space/AddressSpace.handler.unit.test.ts @@ -15,17 +15,13 @@ import { StopTsoData } from "../../../__resources__/StopTsoData"; import { IHandlerParameters, ImperativeError } from "@zowe/imperative"; import * as AddressSpaceHandler from "../../../../../src/zostso/stop/address-space/AddressSpace.handler"; import * as AddressSpaceDefinition from "../../../../../src/zostso/stop/address-space/AddressSpace.definition"; -import { - UNIT_TEST_ZOSMF_PROF_OPTS, - UNIT_TEST_PROFILES_ZOSMF -} from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/TestConstants"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_ZOSMF_PROF_OPTS, positionals: ["zos-tso", "stop", "address-space"], - definition: AddressSpaceDefinition.AddressSpaceDefinition, - profiles: UNIT_TEST_PROFILES_ZOSMF + definition: AddressSpaceDefinition.AddressSpaceDefinition }); describe("stop address-space handler tests", () => { diff --git a/packages/cli/__tests__/zostso/__unit__/stop/address-space/__snapshots__/AddressSpace.definition.unit.test.ts.snap b/packages/cli/__tests__/zostso/__unit__/stop/address-space/__snapshots__/AddressSpace.definition.unit.test.ts.snap index 3e7c4c8f8b..3b152c9d65 100644 --- a/packages/cli/__tests__/zostso/__unit__/stop/address-space/__snapshots__/AddressSpace.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zostso/__unit__/stop/address-space/__snapshots__/AddressSpace.definition.unit.test.ts.snap @@ -26,6 +26,7 @@ Object { "zosmf", ], }, + "summary": "Stop a TSO address space", "type": "command", } `; diff --git a/packages/cli/__tests__/zosuss/__integration__/issue/__snapshots__/cli.zos-uss.issue.ssh.integration.test.ts.snap b/packages/cli/__tests__/zosuss/__integration__/issue/__snapshots__/cli.zos-uss.issue.ssh.integration.test.ts.snap index f0467bfe31..26bc94f6ef 100644 --- a/packages/cli/__tests__/zosuss/__integration__/issue/__snapshots__/cli.zos-uss.issue.ssh.integration.test.ts.snap +++ b/packages/cli/__tests__/zosuss/__integration__/issue/__snapshots__/cli.zos-uss.issue.ssh.integration.test.ts.snap @@ -26,14 +26,14 @@ exports[`zos-uss issue ssh command should display the help 1`] = ` command (string) - z/OS USS command to issue + z/OS USS command to issue. OPTIONS ------- --cwd (string) - Working directory in which to execute the command + Working directory in which to execute the command. Z/OS SSH CONNECTION OPTIONS --------------------------- @@ -139,21 +139,8 @@ exports[`zos-uss issue ssh command should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"The help was constructed for command: command.\\", - \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n command | cmd | ssh\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Issue a z/OS USS command\\\\n\\\\n Note: The common CLI 'Base Connection Options' of token-type and token-value are\\\\n not applicable to the ssh command, since the ssh service is not accessible\\\\n through APIML.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-ssh issue command [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n command\\\\t\\\\t (string)\\\\n\\\\n z/OS USS command to issue\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --cwd (string)\\\\n\\\\n Working directory in which to execute the command\\\\n\\\\n Z/OS SSH CONNECTION OPTIONS\\\\n ---------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OS SSH server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OS SSH server port.\\\\n\\\\n Default value: 22\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe password, which can be the same as your TSO password.\\\\n\\\\n --privateKey | --key | --pk (string)\\\\n\\\\n Path to a file containing your private key, that must match a public key stored\\\\n in the server for authentication\\\\n\\\\n --keyPassphrase | --passphrase | --kp (string)\\\\n\\\\n Private key passphrase, which unlocks the private key.\\\\n\\\\n --handshakeTimeout | --timeout | --to (number)\\\\n\\\\n How long in milliseconds to wait for the SSH handshake to complete.\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --ssh-profile | --ssh-p (string)\\\\n\\\\n The name of a (ssh) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication.\\\\n\\\\n Note: The CLI does not support certificate files that require a password. For\\\\n more information, search Troubleshooting PEM Certificates in Zowe Docs.\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Issue a simple command, giving the working directory:\\\\n\\\\n $ zowe zos-ssh issue command \\\\\\"npm install express\\\\\\" --cwd /u/cicprov/mnt/CICPY01I/bundles/myapp \\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n command | cmd | ssh\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Issue a z/OS USS command\\\\n\\\\n Note: The common CLI 'Base Connection Options' of token-type and token-value are\\\\n not applicable to the ssh command, since the ssh service is not accessible\\\\n through APIML.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-ssh issue command [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n command\\\\t\\\\t (string)\\\\n\\\\n z/OS USS command to issue.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --cwd (string)\\\\n\\\\n Working directory in which to execute the command.\\\\n\\\\n Z/OS SSH CONNECTION OPTIONS\\\\n ---------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OS SSH server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OS SSH server port.\\\\n\\\\n Default value: 22\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe password, which can be the same as your TSO password.\\\\n\\\\n --privateKey | --key | --pk (string)\\\\n\\\\n Path to a file containing your private key, that must match a public key stored\\\\n in the server for authentication\\\\n\\\\n --keyPassphrase | --passphrase | --kp (string)\\\\n\\\\n Private key passphrase, which unlocks the private key.\\\\n\\\\n --handshakeTimeout | --timeout | --to (number)\\\\n\\\\n How long in milliseconds to wait for the SSH handshake to complete.\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --ssh-profile | --ssh-p (string)\\\\n\\\\n The name of a (ssh) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication.\\\\n\\\\n Note: The CLI does not support certificate files that require a password. For\\\\n more information, search Troubleshooting PEM Certificates in Zowe Docs.\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Issue a simple command, giving the working directory:\\\\n\\\\n $ zowe zos-ssh issue command \\\\\\"npm install express\\\\\\" --cwd /u/cicprov/mnt/CICPY01I/bundles/myapp \\\\n\\\\n\\", \\"stderr\\": \\"\\", - \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n command | cmd | ssh\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Issue a z/OS USS command\\\\n\\\\n Note: The common CLI 'Base Connection Options' of token-type and token-value are\\\\n not applicable to the ssh command, since the ssh service is not accessible\\\\n through APIML.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-ssh issue command [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n command\\\\t\\\\t (string)\\\\n\\\\n z/OS USS command to issue\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --cwd (string)\\\\n\\\\n Working directory in which to execute the command\\\\n\\\\n Z/OS SSH CONNECTION OPTIONS\\\\n ---------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OS SSH server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OS SSH server port.\\\\n\\\\n Default value: 22\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe password, which can be the same as your TSO password.\\\\n\\\\n --privateKey | --key | --pk (string)\\\\n\\\\n Path to a file containing your private key, that must match a public key stored\\\\n in the server for authentication\\\\n\\\\n --keyPassphrase | --passphrase | --kp (string)\\\\n\\\\n Private key passphrase, which unlocks the private key.\\\\n\\\\n --handshakeTimeout | --timeout | --to (number)\\\\n\\\\n How long in milliseconds to wait for the SSH handshake to complete.\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --ssh-profile | --ssh-p (string)\\\\n\\\\n The name of a (ssh) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication.\\\\n\\\\n Note: The CLI does not support certificate files that require a password. For\\\\n more information, search Troubleshooting PEM Certificates in Zowe Docs.\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Issue a simple command, giving the working directory:\\\\n\\\\n $ zowe zos-ssh issue command \\\\\\"npm install express\\\\\\" --cwd /u/cicprov/mnt/CICPY01I/bundles/myapp \\\\n\\\\n\\" + \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n command | cmd | ssh\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Issue a z/OS USS command\\\\n\\\\n Note: The common CLI 'Base Connection Options' of token-type and token-value are\\\\n not applicable to the ssh command, since the ssh service is not accessible\\\\n through APIML.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-ssh issue command [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n command\\\\t\\\\t (string)\\\\n\\\\n z/OS USS command to issue.\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --cwd (string)\\\\n\\\\n Working directory in which to execute the command.\\\\n\\\\n Z/OS SSH CONNECTION OPTIONS\\\\n ---------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OS SSH server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OS SSH server port.\\\\n\\\\n Default value: 22\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe password, which can be the same as your TSO password.\\\\n\\\\n --privateKey | --key | --pk (string)\\\\n\\\\n Path to a file containing your private key, that must match a public key stored\\\\n in the server for authentication\\\\n\\\\n --keyPassphrase | --passphrase | --kp (string)\\\\n\\\\n Private key passphrase, which unlocks the private key.\\\\n\\\\n --handshakeTimeout | --timeout | --to (number)\\\\n\\\\n How long in milliseconds to wait for the SSH handshake to complete.\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --ssh-profile | --ssh-p (string)\\\\n\\\\n The name of a (ssh) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication.\\\\n\\\\n Note: The CLI does not support certificate files that require a password. For\\\\n more information, search Troubleshooting PEM Certificates in Zowe Docs.\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Issue a simple command, giving the working directory:\\\\n\\\\n $ zowe zos-ssh issue command \\\\\\"npm install express\\\\\\" --cwd /u/cicprov/mnt/CICPY01I/bundles/myapp \\\\n\\\\n\\" }" `; - -exports[`zos-uss issue ssh command should fail due to invalid ssh command 1`] = ` -"Command Error: -Unknown argument: ss -Command failed due to improper syntax -Did you mean: zos-uss issue ssh? - -Command entered: \\"zos-uss issue ss\\" -Use \\"zowe --help\\" to view groups, commands, and options. -Error Details: -Unknown argument: ss -" -`; diff --git a/packages/cli/__tests__/zosuss/__integration__/issue/cli.zos-uss.issue.ssh.integration.test.ts b/packages/cli/__tests__/zosuss/__integration__/issue/cli.zos-uss.issue.ssh.integration.test.ts index 2d2e4d340f..162b1e9c10 100644 --- a/packages/cli/__tests__/zosuss/__integration__/issue/cli.zos-uss.issue.ssh.integration.test.ts +++ b/packages/cli/__tests__/zosuss/__integration__/issue/cli.zos-uss.issue.ssh.integration.test.ts @@ -38,7 +38,11 @@ describe("zos-uss issue ssh command", () => { it("should fail due to invalid ssh command", async () => { const response = runCliScript(__dirname + "/__scripts__/issue_missing_ssh.sh", TEST_ENVIRONMENT); - expect(response.stderr.toString()).toMatchSnapshot(); + expect(response.stdout.toString()).toBe(''); + expect(response.stderr.toString()).toContain('Unknown argument: ss'); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Did you mean: zos-uss issue ssh'); + expect(response.stderr.toString()).toContain('Command entered: "zos-uss issue ss"'); + expect(response.stderr.toString()).toContain('Use "zowe --help" to view groups, commands, and options.'); }); - }); diff --git a/packages/cli/__tests__/zosuss/__unit__/issue/ssh/Ssh.handler.unit.test.ts b/packages/cli/__tests__/zosuss/__unit__/issue/ssh/Ssh.handler.unit.test.ts index 58c1fedba0..c7bdc2efab 100644 --- a/packages/cli/__tests__/zosuss/__unit__/issue/ssh/Ssh.handler.unit.test.ts +++ b/packages/cli/__tests__/zosuss/__unit__/issue/ssh/Ssh.handler.unit.test.ts @@ -11,7 +11,7 @@ jest.mock("../../../../../../zosuss/lib/Shell"); -import { IHandlerParameters, IProfile, CommandProfiles, ConnectionPropsForSessCfg } from "@zowe/imperative"; +import { IHandlerParameters, ConnectionPropsForSessCfg } from "@zowe/imperative"; import SshHandler from "../../../../../src/zosuss/issue/ssh/Ssh.handler"; import * as SshDefinition from "../../../../../src/zosuss/issue/ssh/Ssh.definition"; import { Shell } from "@zowe/zos-uss-for-zowe-sdk"; @@ -47,73 +47,28 @@ const UNIT_TEST_SSH_PROF_OPTS_PRIVATE_KEY_WITH_PASSPHRASE_NO_USER = { keyPassPhrase: "dummyPassPhrase123" }; - -// A mocked profile map with ssh profile -const UNIT_TEST_PROFILE_MAP = new Map(); -UNIT_TEST_PROFILE_MAP.set( - "ssh", [{ - name: "ssh", - type: "ssh", - ...UNIT_TEST_SSH_PROF_OPTS - }] -); -const UNIT_TEST_PROFILES_SSH = new CommandProfiles(UNIT_TEST_PROFILE_MAP); - -const UNIT_TEST_PROFILE_MAP_PRIVATE_KEY = new Map(); -UNIT_TEST_PROFILE_MAP_PRIVATE_KEY.set( - "ssh", [{ - name: "ssh", - type: "ssh", - ...UNIT_TEST_SSH_PROF_OPTS_PRIVATE_KEY - }] -); -const UNIT_TEST_PROFILE_MAP_PRIVATE_KEY_WITH_PASSPHRASE = new Map(); -UNIT_TEST_PROFILE_MAP_PRIVATE_KEY_WITH_PASSPHRASE.set( - "ssh", [{ - name: "ssh", - type: "ssh", - ...UNIT_TEST_SSH_PROF_OPTS_PRIVATE_KEY_WITH_PASSPHRASE - }] -); -const UNIT_TEST_PROFILE_MAP_PRIVATE_KEY_WITH_PASSPHRASE_NO_USER = new Map(); -UNIT_TEST_PROFILE_MAP_PRIVATE_KEY_WITH_PASSPHRASE.set( - "ssh", [{ - name: "ssh", - type: "ssh", - ...UNIT_TEST_SSH_PROF_OPTS_PRIVATE_KEY_WITH_PASSPHRASE_NO_USER - }] -); - -const UNIT_TEST_PROFILES_SSH_PRIVATE_KEY = new CommandProfiles(UNIT_TEST_PROFILE_MAP_PRIVATE_KEY); -const UNIT_TEST_PROFILES_SSH_PRIVATE_KEY_WITH_PASSPHRASE = new CommandProfiles(UNIT_TEST_PROFILE_MAP_PRIVATE_KEY_WITH_PASSPHRASE); -const UNIT_TEST_PROFILES_SSH_PRIVATE_KEY_WITH_PASSPHRASE_NO_USER = new CommandProfiles(UNIT_TEST_PROFILE_MAP_PRIVATE_KEY_WITH_PASSPHRASE_NO_USER); - // Mocked parameters for the unit tests const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_SSH_PROF_OPTS, positionals: ["zos-uss", "issue", "ssh"], - definition: SshDefinition.SshDefinition, - profiles: UNIT_TEST_PROFILES_SSH + definition: SshDefinition.SshDefinition }); const DEFAULT_PARAMETERS_PRIVATE_KEY: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_SSH_PROF_OPTS_PRIVATE_KEY, positionals: ["zos-uss", "issue", "ssh"], - definition: SshDefinition.SshDefinition, - profiles: UNIT_TEST_PROFILES_SSH_PRIVATE_KEY + definition: SshDefinition.SshDefinition }); const DEFAULT_PARAMETERS_KEY_PASSPHRASE: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_SSH_PROF_OPTS_PRIVATE_KEY_WITH_PASSPHRASE, positionals: ["zos-uss", "issue", "ssh"], - definition: SshDefinition.SshDefinition, - profiles: UNIT_TEST_PROFILES_SSH_PRIVATE_KEY_WITH_PASSPHRASE, + definition: SshDefinition.SshDefinition }); const DEFAULT_PARAMETERS_KEY_PASSPHRASE_NO_USER: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_SSH_PROF_OPTS_PRIVATE_KEY_WITH_PASSPHRASE_NO_USER, positionals: ["zos-uss", "issue", "ssh"], - definition: SshDefinition.SshDefinition, - profiles: UNIT_TEST_PROFILES_SSH_PRIVATE_KEY_WITH_PASSPHRASE_NO_USER, + definition: SshDefinition.SshDefinition }); const testOutput = "TEST OUTPUT"; diff --git a/packages/cli/__tests__/zosuss/__unit__/issue/ssh/__snapshots__/Ssh.definition.unit.test.ts.snap b/packages/cli/__tests__/zosuss/__unit__/issue/ssh/__snapshots__/Ssh.definition.unit.test.ts.snap index 7c8232b0e6..4a46c638fa 100644 --- a/packages/cli/__tests__/zosuss/__unit__/issue/ssh/__snapshots__/Ssh.definition.unit.test.ts.snap +++ b/packages/cli/__tests__/zosuss/__unit__/issue/ssh/__snapshots__/Ssh.definition.unit.test.ts.snap @@ -3,7 +3,7 @@ exports[`zos-uss issue ssh command definition should not have changed 1`] = ` Array [ Object { - "description": "Working directory in which to execute the command", + "description": "Working directory in which to execute the command.", "name": "cwd", "type": "string", }, diff --git a/packages/cli/package.json b/packages/cli/package.json index e3a9b8b48e..41a926d4b2 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,7 @@ { "name": "@zowe/cli", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", + "zoweVersion": "v3.0.0", "description": "Zowe CLI is a command line interface (CLI) that provides a simple and streamlined way to interact with IBM z/OS.", "author": "Zowe", "license": "EPL-2.0", @@ -13,7 +14,6 @@ "url": "https://github.com/zowe/zowe-cli.git" }, "bin": { - "bright": "./lib/main.js", "zowe": "./lib/main.js" }, "keywords": [ @@ -58,36 +58,35 @@ "preshrinkwrap": "node ../../scripts/rewriteShrinkwrap.js" }, "dependencies": { - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1", - "@zowe/provisioning-for-zowe-sdk": "7.29.2", - "@zowe/zos-console-for-zowe-sdk": "7.29.2", - "@zowe/zos-files-for-zowe-sdk": "7.29.2", - "@zowe/zos-jobs-for-zowe-sdk": "7.29.2", - "@zowe/zos-logs-for-zowe-sdk": "7.29.2", - "@zowe/zos-tso-for-zowe-sdk": "7.29.2", - "@zowe/zos-uss-for-zowe-sdk": "7.29.2", - "@zowe/zos-workflows-for-zowe-sdk": "7.29.2", - "@zowe/zosmf-for-zowe-sdk": "7.29.2", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528", + "@zowe/provisioning-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/zos-console-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/zos-jobs-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/zos-logs-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/zos-tso-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/zos-uss-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/zos-workflows-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/zosmf-for-zowe-sdk": "8.0.0-next.202409111528", "find-process": "1.4.7", - "get-stream": "6.0.1", "lodash": "4.17.21", - "minimatch": "5.0.1", + "minimatch": "9.0.5", "tar": "6.2.1" }, "devDependencies": { - "@types/diff": "^5.0.2", - "@types/lodash": "^4.14.175", - "@types/tar": "^6.1.2", - "@zowe/cli-test-utils": "7.29.2", - "comment-json": "^4.1.1", + "@types/diff": "^5.0.9", + "@types/lodash": "^4.17.6", + "@types/tar": "^6.1.11", + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "comment-json": "^4.2.3", "strip-ansi": "^6.0.1", - "which": "^2.0.2" + "which": "^4.0.0" }, "optionalDependencies": { - "@zowe/secrets-for-zowe-sdk": "7.18.6" + "@zowe/secrets-for-zowe-sdk": "8.0.0-next.202409111528" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.12.0" } } diff --git a/packages/cli/scripts/validatePlugins.js b/packages/cli/scripts/validatePlugins.js index 4fe0a6046c..db43b1798b 100644 --- a/packages/cli/scripts/validatePlugins.js +++ b/packages/cli/scripts/validatePlugins.js @@ -10,8 +10,8 @@ */ /* Validate any existing plugins. We do this when the user has re-installed - * brightside. It is a safety net to validate whether any existing plugins - * are incompatible with newly installed brightside/imperative. + * Zowe. It is a safety net to validate whether any existing plugins + * are incompatible with newly installed Zowe. * * This script is run in our package.json:scripts:postinstall as: * node ./scripts/validatePlugins.js @@ -25,23 +25,13 @@ function validatePlugins() { const fs = require('fs'); + const { spawnSync } = require('child_process'); // only run the zowe command when main has been built const zowePgm = process.cwd() + "/lib/main.js"; if (fs.existsSync(zowePgm)) { - /* Imperative gets its root directory from the mainModule filename, - * which is currently set to this script. Make it look like the script - * being run by NodeJS is main.js. - */ - process.mainModule.filename = zowePgm; - - // add the parameters for the zowe command to validate plugins - process.argv.push("plugins"); - process.argv.push("validate"); - process.argv.push("--no-fail-on-error"); - console.log("Since you re-installed Zowe CLI, we are re-validating any plugins."); - require(zowePgm); + spawnSync("node " + zowePgm + " plugins validate --no-fail-on-error", {shell: true, stdio: "inherit", cwd: process.cwd(), windowsHide: true}); } } diff --git a/packages/cli/src/Constants.ts b/packages/cli/src/Constants.ts index ca5265873f..2410b076f2 100644 --- a/packages/cli/src/Constants.ts +++ b/packages/cli/src/Constants.ts @@ -9,7 +9,6 @@ * */ -import { ProfileConstants } from "@zowe/core-for-zowe-sdk"; /** * Class to contain constants @@ -23,7 +22,7 @@ export class Constants { * @static * @memberof Constants */ - public static readonly LOG_LOCATION = "zowe/logs/zowe.log"; + public static readonly LOG_LOCATION = "logs/zowe.log"; /** * Display name @@ -91,138 +90,4 @@ For ${Constants.DISPLAY_NAME} support, visit ${Constants.SUPPORT_LINK} * @memberof Constants */ public static readonly HOME_DIR = "~/.zowe"; - - //______________________________________________________________________ - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly BASE_CONNECTION_OPTION_GROUP = ProfileConstants.BASE_CONNECTION_OPTION_GROUP; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly BASE_OPTION_HOST = ProfileConstants.BASE_OPTION_HOST; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly BASE_OPTION_PORT = ProfileConstants.BASE_OPTION_PORT; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly BASE_OPTION_USER = ProfileConstants.BASE_OPTION_USER; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly BASE_OPTION_PASSWORD = ProfileConstants.BASE_OPTION_PASSWORD; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly BASE_OPTION_REJECT_UNAUTHORIZED = ProfileConstants.BASE_OPTION_REJECT_UNAUTHORIZED; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly BASE_OPTION_TOKEN_TYPE = ProfileConstants.BASE_OPTION_TOKEN_TYPE; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly BASE_OPTION_TOKEN_VALUE = ProfileConstants.BASE_OPTION_TOKEN_VALUE; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly BASE_OPTION_CERT_FILE = ProfileConstants.BASE_OPTION_CERT_FILE; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly BASE_OPTION_CERT_KEY_FILE = ProfileConstants.BASE_OPTION_CERT_KEY_FILE; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - // public static readonly BASE_OPTION_CERT_FILE_PASSPHRASE = ProfileConstants.BASE_OPTION_CERT_FILE_PASSPHRASE - - //______________________________________________________________________ - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly AUTO_INIT_OPTION_GROUP = ProfileConstants.AUTO_INIT_OPTION_GROUP; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly AUTO_INIT_OPTION_HOST = ProfileConstants.AUTO_INIT_OPTION_HOST; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly AUTO_INIT_OPTION_PORT = ProfileConstants.AUTO_INIT_OPTION_PORT; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly AUTO_INIT_OPTION_USER = ProfileConstants.AUTO_INIT_OPTION_USER; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly AUTO_INIT_OPTION_PASSWORD = ProfileConstants.AUTO_INIT_OPTION_PASSWORD; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly AUTO_INIT_OPTION_REJECT_UNAUTHORIZED = ProfileConstants.AUTO_INIT_OPTION_REJECT_UNAUTHORIZED; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly AUTO_INIT_OPTION_TOKEN_TYPE = ProfileConstants.AUTO_INIT_OPTION_TOKEN_TYPE; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly AUTO_INIT_OPTION_TOKEN_VALUE = ProfileConstants.AUTO_INIT_OPTION_TOKEN_VALUE; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly AUTO_INIT_OPTION_CERT_FILE = ProfileConstants.AUTO_INIT_OPTION_CERT_FILE; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly AUTO_INIT_OPTION_CERT_KEY_FILE = ProfileConstants.AUTO_INIT_OPTION_CERT_KEY_FILE; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly AUTH_GROUP_SUMMARY = ProfileConstants.AUTH_GROUP_SUMMARY; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly AUTH_GROUP_DESCRIPTION = ProfileConstants.AUTH_GROUP_DESCRIPTION; - - //______________________________________________________________________ - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly APIML_LOGIN_SUMMARY = ProfileConstants.APIML_LOGIN_SUMMARY; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly APIML_LOGIN_DESCRIPTION = ProfileConstants.APIML_LOGIN_DESCRIPTION; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly APIML_LOGIN_EXAMPLE1 = ProfileConstants.APIML_LOGIN_EXAMPLE1; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly APIML_LOGIN_EXAMPLE2 = ProfileConstants.APIML_LOGIN_EXAMPLE2; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly APIML_LOGOUT_SUMMARY = ProfileConstants.APIML_LOGOUT_SUMMARY; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly APIML_LOGOUT_DESCRIPTION = ProfileConstants.APIML_LOGOUT_DESCRIPTION; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly APIML_LOGOUT_EXAMPLE1 = ProfileConstants.APIML_LOGOUT_EXAMPLE1; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly APIML_LOGOUT_EXAMPLE2 = ProfileConstants.APIML_LOGOUT_EXAMPLE2; - /** - * @deprecated Please use this constant from the @zowe/core-for-zowe-sdk - */ - public static readonly APIML_LOGOUT_OPTION_TOKEN_TYPE = ProfileConstants.APIML_LOGOUT_OPTION_TOKEN_TYPE; } diff --git a/packages/cli/src/config/auto-init/ApimlAutoInitHandler.ts b/packages/cli/src/config/auto-init/ApimlAutoInitHandler.ts index 7192b93e80..0078731ad7 100644 --- a/packages/cli/src/config/auto-init/ApimlAutoInitHandler.ts +++ b/packages/cli/src/config/auto-init/ApimlAutoInitHandler.ts @@ -15,7 +15,7 @@ import * as lodash from "lodash"; import { ZosmfSession } from "@zowe/zosmf-for-zowe-sdk"; import { BaseAutoInitHandler, AbstractSession, ICommandArguments, IConfig, IConfigProfile, ISession, IHandlerResponseApi, IHandlerParameters, SessConstants, ImperativeConfig, - ImperativeError, RestClientError, TextUtils, Config + ImperativeError, RestClientError, TextUtils, Config, ConfigUtils } from "@zowe/imperative"; import { IApimlProfileInfo, IAutoInitRpt, IProfileRpt, Login, Services } from "@zowe/core-for-zowe-sdk"; @@ -70,6 +70,7 @@ export default class ApimlAutoInitHandler extends BaseAutoInitHandler { */ protected async doAutoInit(session: AbstractSession, params: IHandlerParameters): Promise { // Login with token authentication first, so we can support certificates + // eslint-disable-next-line no-extra-parens if ((session.ISession.user && session.ISession.password) || (session.ISession.cert && session.ISession.certKey)) { // If it is basic authentication, we need to set the auth type. if (session.ISession.tokenType == null) { @@ -107,9 +108,15 @@ export default class ApimlAutoInitHandler extends BaseAutoInitHandler { // Check to see if there is an active base profile to avoid creating a new one named "base" let activeBaseProfile = params.arguments[`${this.mProfileType}-profile`] || config.properties.defaults[this.mProfileType]; let baseProfileCreated = false; + // Populate the config with base profile information if (activeBaseProfile == null) { - profileConfig.profiles[this.mProfileType] = { + + // Name our base profile differently in a global config vs a project config + const globalConfig: boolean = params.arguments?.globalConfig ? true : false; + activeBaseProfile = ConfigUtils.formGlobOrProjProfileNm(this.mProfileType, globalConfig); + + profileConfig.profiles[activeBaseProfile] = { type: this.mProfileType, properties: { host: session.ISession.hostname, @@ -118,7 +125,6 @@ export default class ApimlAutoInitHandler extends BaseAutoInitHandler { }, secure: [] }; - activeBaseProfile = this.mProfileType; baseProfileCreated = true; } else { const oldBaseProfile = this.getOldBaseProfileProps(config, activeBaseProfile); @@ -148,7 +154,7 @@ export default class ApimlAutoInitHandler extends BaseAutoInitHandler { // Report whether or not we created a base profile in this auto-init execution this.mAutoInitReport.profileRpts.push({ - profName: this.mProfileType, + profName: activeBaseProfile, profType: this.mProfileType, changeForProf: baseProfileCreated ? "created" : "modified", basePath: null, @@ -247,7 +253,7 @@ export default class ApimlAutoInitHandler extends BaseAutoInitHandler { if (!baseOverride.secure) { msg += `'${baseOverride.priorityValue}' overrides '${baseOverride.baseValue}' in`; } else { - msg += "secure value " + ((baseOverride.priorityValue != null) ? "overrides" : "may override"); + msg += "secure value " + (baseOverride.priorityValue != null ? "overrides" : "may override"); } msg += ` profile '${baseProfileName}'`; } @@ -510,7 +516,7 @@ export default class ApimlAutoInitHandler extends BaseAutoInitHandler { }); } } - for (const name of (baseProfile.secure || [])) { + for (const name of baseProfile.secure || []) { if (serviceProfile.secure?.includes(name)) { profileRpt.baseOverrides.push({ propName: name, secure: true }); } diff --git a/packages/cli/src/daemon/disable/Disable.definition.ts b/packages/cli/src/daemon/disable/Disable.definition.ts index 0e58916f9e..85d821222f 100644 --- a/packages/cli/src/daemon/disable/Disable.definition.ts +++ b/packages/cli/src/daemon/disable/Disable.definition.ts @@ -13,7 +13,8 @@ import { ICommandDefinition } from "@zowe/imperative"; export const DisableCommand: ICommandDefinition = { name: "disable", - description: "Disables daemon-mode operation of the Zowe CLI.", + summary: "Disable daemon-mode operation of the Zowe CLI", + description: "Disable daemon-mode operation of the Zowe CLI.", type: "command", handler: __dirname + "/Disable.handler", examples: [ diff --git a/packages/cli/src/daemon/disable/Disable.handler.ts b/packages/cli/src/daemon/disable/Disable.handler.ts index 95bc0ce61e..a7a0fbee8e 100644 --- a/packages/cli/src/daemon/disable/Disable.handler.ts +++ b/packages/cli/src/daemon/disable/Disable.handler.ts @@ -163,12 +163,12 @@ export default class DisableDaemonHandler implements ICommandHandler { ); return null; } - if (typeof(pidFileContents?.pid) === "number" && Number.isInteger(pidFileContents?.pid)) { + if (typeof pidFileContents?.pid === "number" && Number.isInteger(pidFileContents?.pid)) { return pidFileContents.pid; } else { Logger.getAppLogger().error(`Daemon PID file '${daemonPidFileNm}' ` + `contains invalid PID value = '${pidFileContents?.pid}' of type ` + - typeof(pidFileContents?.pid) + typeof pidFileContents?.pid ); } } catch(caughtErr) { diff --git a/packages/cli/src/daemon/enable/Enable.definition.ts b/packages/cli/src/daemon/enable/Enable.definition.ts index 17e7ba337a..2028496f9c 100644 --- a/packages/cli/src/daemon/enable/Enable.definition.ts +++ b/packages/cli/src/daemon/enable/Enable.definition.ts @@ -13,7 +13,8 @@ import { ICommandDefinition } from "@zowe/imperative"; export const EnableCommand: ICommandDefinition = { name: "enable", - description: "Enables daemon-mode operation of the Zowe CLI. " + + summary: "Enable daemon-mode operation of the Zowe CLI", + description: "Enable daemon-mode operation of the Zowe CLI. " + "You only need to run the enable command once after each " + "new installation of the Zowe CLI. Afterwards, any zowe command " + "will automatically start a daemon as needed.", diff --git a/packages/cli/src/daemon/restart/Restart.definition.ts b/packages/cli/src/daemon/restart/Restart.definition.ts index 9d46676e6d..b4f07aeca7 100644 --- a/packages/cli/src/daemon/restart/Restart.definition.ts +++ b/packages/cli/src/daemon/restart/Restart.definition.ts @@ -13,6 +13,7 @@ import { ICommandDefinition } from "@zowe/imperative"; export const RestartCommand: ICommandDefinition = { name: "restart", + summary: "Restart the Zowe CLI daemon", description: "Restart the Zowe CLI daemon.", type: "command", handler: __dirname + "/Restart.handler", diff --git a/packages/cli/src/provisioning/delete/Delete.definition.ts b/packages/cli/src/provisioning/delete/Delete.definition.ts index 8cb32b6589..77a645cbe4 100644 --- a/packages/cli/src/provisioning/delete/Delete.definition.ts +++ b/packages/cli/src/provisioning/delete/Delete.definition.ts @@ -17,7 +17,7 @@ export const DeleteCommand: ICommandDefinition = { name: "delete", aliases: ["del"], type: "group", - summary: "Delete instance.", + summary: "Delete instance", description: "Deletes instance previously provisioned with z/OSMF cloud provisioning services.", children: [DeleteInstanceDefinition] }; diff --git a/packages/cli/src/provisioning/delete/instance/DeleteInstance.definition.ts b/packages/cli/src/provisioning/delete/instance/DeleteInstance.definition.ts index 89ee90a04d..3a731517e8 100644 --- a/packages/cli/src/provisioning/delete/instance/DeleteInstance.definition.ts +++ b/packages/cli/src/provisioning/delete/instance/DeleteInstance.definition.ts @@ -15,7 +15,7 @@ export const DeleteInstanceDefinition: ICommandDefinition = { name: "instance", aliases: ["i"], type: "command", - summary: "Deletes instance.", + summary: "Deletes instance", description: "Deletes selected deprovisioned instance.", handler: __dirname + "/DeleteInstance.handler", profile: { diff --git a/packages/cli/src/provisioning/list/catalogTemplates/CatalogTemplates.definition.ts b/packages/cli/src/provisioning/list/catalogTemplates/CatalogTemplates.definition.ts index 19d99b7943..6e0d6589d7 100644 --- a/packages/cli/src/provisioning/list/catalogTemplates/CatalogTemplates.definition.ts +++ b/packages/cli/src/provisioning/list/catalogTemplates/CatalogTemplates.definition.ts @@ -16,7 +16,7 @@ export const catalogTemplates: ICommandDefinition = { name: "catalog-templates", aliases: ["ct"], type: "command", - summary: "List z/OSMF published catalog templates.", + summary: "List z/OSMF published catalog templates", description: "Lists the z/OSMF service catalog published templates.", handler: path.join(__dirname, "/CatalogTemplates.handler"), profile: { diff --git a/packages/cli/src/provisioning/list/instanceInfo/InstanceInfo.definition.ts b/packages/cli/src/provisioning/list/instanceInfo/InstanceInfo.definition.ts index a518dd954a..a5a1a92d4d 100644 --- a/packages/cli/src/provisioning/list/instanceInfo/InstanceInfo.definition.ts +++ b/packages/cli/src/provisioning/list/instanceInfo/InstanceInfo.definition.ts @@ -16,7 +16,7 @@ export const instanceInfo: ICommandDefinition = { name: "instance-info", aliases: ["ii"], type: "command", - summary: "List Provisioned Instance Details.", + summary: "List Provisioned Instance Details", description: "List details about an instance provisioned with z/OSMF.", handler: path.join(__dirname, "/InstanceInfo.handler"), profile: { diff --git a/packages/cli/src/provisioning/list/instanceVariables/InstanceVariables.definition.ts b/packages/cli/src/provisioning/list/instanceVariables/InstanceVariables.definition.ts index 1bcaec3e2a..9627c0229f 100644 --- a/packages/cli/src/provisioning/list/instanceVariables/InstanceVariables.definition.ts +++ b/packages/cli/src/provisioning/list/instanceVariables/InstanceVariables.definition.ts @@ -16,7 +16,7 @@ export const instanceVariables: ICommandDefinition = { name: "instance-variables", aliases: ["iv"], type: "command", - summary: "List Instance Variables and Values.", + summary: "List Instance Variables and Values", description: "List a set of variables and their values for a given name.", handler: path.join(__dirname, "/InstanceVariables.handler"), profile: { diff --git a/packages/cli/src/provisioning/list/registry/RegistryInstances.definition.ts b/packages/cli/src/provisioning/list/registry/RegistryInstances.definition.ts index 5a689c46d5..03b7f7a5db 100644 --- a/packages/cli/src/provisioning/list/registry/RegistryInstances.definition.ts +++ b/packages/cli/src/provisioning/list/registry/RegistryInstances.definition.ts @@ -16,7 +16,7 @@ export const registryInstances: ICommandDefinition = { name: "registry-instances", aliases: ["ri"], type: "command", - summary: "List provisioned instances.", + summary: "List provisioned instances", description: "List the provisioned instances from the z/OSMF software registry.", handler: path.join(__dirname, "/RegistryInstances.handler"), profile: { diff --git a/packages/cli/src/provisioning/list/registry/RegistryInstances.handler.ts b/packages/cli/src/provisioning/list/registry/RegistryInstances.handler.ts index 2adec99ffc..66537eb397 100644 --- a/packages/cli/src/provisioning/list/registry/RegistryInstances.handler.ts +++ b/packages/cli/src/provisioning/list/registry/RegistryInstances.handler.ts @@ -43,7 +43,7 @@ export default class RegistryInstancesHandler extends ZosmfBaseHandler { commandParameters.response.console.log(TextUtils.prettyJson(unique)); } else { commandParameters.response.console.log("z/OSMF Service Registry"); - if (!(commandParameters.arguments.filterByType == null)) { + if (commandParameters.arguments.filterByType != null) { commandParameters.response.console.log("\nShowing ONLY \"" + commandParameters.arguments.filterByType.toUpperCase() + "\" instance types."); } diff --git a/packages/cli/src/provisioning/list/templateInfo/TemplateInfo.definition.ts b/packages/cli/src/provisioning/list/templateInfo/TemplateInfo.definition.ts index 05d499dcc1..abbd546d10 100644 --- a/packages/cli/src/provisioning/list/templateInfo/TemplateInfo.definition.ts +++ b/packages/cli/src/provisioning/list/templateInfo/TemplateInfo.definition.ts @@ -16,7 +16,7 @@ export const templateInfo: ICommandDefinition = { name: "template-info", aliases: ["ti"], type: "command", - summary: "List Published Template Details.", + summary: "List Published Template Details", description: "List details about a template published with z/OSMF Cloud Provisioning.", handler: path.join(__dirname, "/TemplateInfo.handler"), profile: { diff --git a/packages/cli/src/provisioning/perform/Perform.definition.ts b/packages/cli/src/provisioning/perform/Perform.definition.ts index dfbb3f13ac..1b68c93da3 100644 --- a/packages/cli/src/provisioning/perform/Perform.definition.ts +++ b/packages/cli/src/provisioning/perform/Perform.definition.ts @@ -17,7 +17,7 @@ export const PerformCommand: ICommandDefinition = { name: "perform", aliases: ["perf"], type: "group", - summary: "Perform instance actions.", + summary: "Perform instance actions", description: "Perform actions against instances provisioned with z/OSMF.", children: [ActionDefinition] }; diff --git a/packages/cli/src/provisioning/perform/action/Action.definition.ts b/packages/cli/src/provisioning/perform/action/Action.definition.ts index 307674eca0..0134cb8ff5 100644 --- a/packages/cli/src/provisioning/perform/action/Action.definition.ts +++ b/packages/cli/src/provisioning/perform/action/Action.definition.ts @@ -15,7 +15,7 @@ export const ActionDefinition: ICommandDefinition = { name: "action", aliases: ["act"], type: "command", - summary: "Perform instance actions.", + summary: "Perform instance actions", description: "Perform actions on instances previously provisioned with z/OSMF cloud\n" + " provisioning services. To view the list of provisioned instances, use the\n" + " \"zowe provisioning list registry-instances\" command. Once you have\n" + diff --git a/packages/cli/src/provisioning/provision/Provision.definition.ts b/packages/cli/src/provisioning/provision/Provision.definition.ts index 14dab7119f..fd9768a806 100644 --- a/packages/cli/src/provisioning/provision/Provision.definition.ts +++ b/packages/cli/src/provisioning/provision/Provision.definition.ts @@ -17,7 +17,7 @@ export const ProvisionCommand: ICommandDefinition = { name: "provision", aliases: ["prov"], type: "group", - summary: "Provision published software service templates.", + summary: "Provision published software service templates", description: "Using z/OSMF cloud provisioning services provision available templates.", children: [TemplateDefinition] }; diff --git a/packages/cli/src/provisioning/provision/template/Template.definition.ts b/packages/cli/src/provisioning/provision/template/Template.definition.ts index 05e65bea33..962623717d 100644 --- a/packages/cli/src/provisioning/provision/template/Template.definition.ts +++ b/packages/cli/src/provisioning/provision/template/Template.definition.ts @@ -16,7 +16,7 @@ export const TemplateDefinition: ICommandDefinition = { name: "template", aliases: ["tem"], type: "command", - summary: "Provision a published software service template.", + summary: "Provision a published software service template", description: "Using z/OSMF cloud provisioning services, provision available templates.\n" + "You can view available templates using the " + Constants.BINARY_NAME + " provisioning list " + "catalog-templates command.", diff --git a/packages/cli/src/provisioning/provision/template/Template.handler.ts b/packages/cli/src/provisioning/provision/template/Template.handler.ts index 979c59d0c9..b4823dd670 100644 --- a/packages/cli/src/provisioning/provision/template/Template.handler.ts +++ b/packages/cli/src/provisioning/provision/template/Template.handler.ts @@ -26,7 +26,7 @@ export default class Handler extends ZosmfBaseHandler { let usedOptionalParms: boolean = false; let arrayOfSystemNickNames: string[]; - if (!(commandParameters.arguments.systemNickNames == null)) { + if (commandParameters.arguments.systemNickNames != null) { arrayOfSystemNickNames = commandParameters.arguments.systemNickNames .split(",") .map((systemName: string) => { @@ -46,9 +46,7 @@ export default class Handler extends ZosmfBaseHandler { ); for (const property in provisionOptionalParams) { - if ( - !(provisionOptionalParams[property as keyof IProvisionOptionals] == null) - ) { + if ( provisionOptionalParams[property as keyof IProvisionOptionals] != null ) { usedOptionalParms = true; } } diff --git a/packages/cli/src/workflows/archive/Archive.definition.ts b/packages/cli/src/workflows/archive/Archive.definition.ts index 62064ace2d..ce29afcb3d 100644 --- a/packages/cli/src/workflows/archive/Archive.definition.ts +++ b/packages/cli/src/workflows/archive/Archive.definition.ts @@ -21,6 +21,7 @@ import { Workflow } from "./workflow/Archive.workflow.definition"; export const ArchiveDefinition: ICommandDefinition = { name: "archive", type: "group", + summary: "Archive workflow instance in z/OSMF", description: "Archive workflow instance in z/OSMF.", children: [ Workflow diff --git a/packages/cli/src/workflows/archive/Archive.handler.ts b/packages/cli/src/workflows/archive/Archive.handler.ts index bf9c8049ad..30fdf5d75b 100644 --- a/packages/cli/src/workflows/archive/Archive.handler.ts +++ b/packages/cli/src/workflows/archive/Archive.handler.ts @@ -52,7 +52,11 @@ export default class ArchiveHandler extends ZosmfBaseHandler { try{ resp = await ArchiveWorkflow.archiveWorkflowByKey(this.mSession, this.arguments.workflowKey, undefined); } catch (err){ - error = "Archive workflow: " + err; + error = new ImperativeError({ + msg: "Archive workflow: " + err, + causeErrors: err.causeErrors, + additionalDetails: err.additionalDetails + }); throw error; } params.response.data.setObj(resp); diff --git a/packages/cli/src/workflows/archive/workflow/Archive.workflow.definition.ts b/packages/cli/src/workflows/archive/workflow/Archive.workflow.definition.ts index 593927712b..81da9775a8 100644 --- a/packages/cli/src/workflows/archive/workflow/Archive.workflow.definition.ts +++ b/packages/cli/src/workflows/archive/workflow/Archive.workflow.definition.ts @@ -28,10 +28,10 @@ export const Workflow: ICommandDefinition = { profile: { optional: ["zosmf"] }, - options: ([ + options: [ ArchiveOptions.workflowName, ArchiveOptions.workflowKey - ]), + ], outputFormatOptions: true, examples: [ { diff --git a/packages/cli/src/workflows/create/Create.common.handler.ts b/packages/cli/src/workflows/create/Create.common.handler.ts index 9939bf3d98..12564c3183 100644 --- a/packages/cli/src/workflows/create/Create.common.handler.ts +++ b/packages/cli/src/workflows/create/Create.common.handler.ts @@ -64,11 +64,12 @@ export default class CreateCommonHandler extends ZosmfBaseHandler { wfKey ); } catch (err) { - error = - "Deleting z/OSMF workflow with workflow name " + - this.arguments.workflowName + - " failed. More details: \n" + - err; + error = new ImperativeError({ + msg: "Deleting z/OSMF workflow with workflow name " + this.arguments.workflowName + " failed.\n" + err, + causeErrors: err.causeErrors, + additionalDetails: err.additionalDetails + }); + throw error; } } } @@ -88,11 +89,11 @@ export default class CreateCommonHandler extends ZosmfBaseHandler { this.arguments.deleteCompleted ); } catch (err) { - error = - "Creating zOS/MF workflow with data set: " + - this.arguments.dataSet + - " failed. More details: \n" + - err; + error = new ImperativeError({ + msg: "Creating z/OSMF workflow with data set: " + this.arguments.dataSet + " failed.\n" + err, + causeErrors: err.causeErrors, + additionalDetails: err.additionalDetails + }); throw error; } params.response.data.setObj(resp); @@ -120,11 +121,11 @@ export default class CreateCommonHandler extends ZosmfBaseHandler { this.arguments.deleteCompleted ); } catch (err) { - error = - "Creating z/OSMF workflow with uss file: " + - this.arguments.ussFile + - " failed. More details: \n" + - err; + error = new ImperativeError({ + msg: "Creating z/OSMF workflow with uss file: " + this.arguments.ussFile + " failed.\n" + err, + causeErrors: err.causeErrors, + additionalDetails: err.additionalDetails + }); throw error; } params.response.data.setObj(resp); @@ -154,11 +155,11 @@ export default class CreateCommonHandler extends ZosmfBaseHandler { this.arguments.remoteDirectory ); } catch (err) { - error = - "Creating z/OSMF workflow with local file: " + - this.arguments.localFile + - " failed. More details: \n" + - err; + error = new ImperativeError({ + msg: "Creating z/OSMF workflow with local file: " + this.arguments.localFile + " failed.\n" + err, + causeErrors: err.causeErrors, + additionalDetails: err.additionalDetails + }); throw error; } params.response.data.setObj(resp); diff --git a/packages/cli/src/workflows/create/Create.common.options.ts b/packages/cli/src/workflows/create/Create.common.options.ts index bd69c962ed..4d59718e4b 100644 --- a/packages/cli/src/workflows/create/Create.common.options.ts +++ b/packages/cli/src/workflows/create/Create.common.options.ts @@ -36,7 +36,7 @@ export const CreateCommonOptions: { [key: string]: ICommandOptionDefinition } = name: "uss-file", aliases: ["uf"], type: "string", - description: "Uss file that contains workflow definition.", + description: "USS file that contains workflow definition.", required: true }, @@ -162,7 +162,7 @@ export const CreateCommonOptions: { [key: string]: ICommandOptionDefinition } = remoteDirectory: { name: "remote-directory", aliases: ["rd"], - description: "The remote uss directory where the files are to be uploaded. The directory has to exist", + description: "The remote USS directory where the files are to be uploaded. The directory has to exist.", type: "string", required: false }, diff --git a/packages/cli/src/workflows/create/Create.definition.ts b/packages/cli/src/workflows/create/Create.definition.ts index c737718e0d..c38198a995 100644 --- a/packages/cli/src/workflows/create/Create.definition.ts +++ b/packages/cli/src/workflows/create/Create.definition.ts @@ -25,6 +25,7 @@ export const CreateDefinition: ICommandDefinition = { name: "create", aliases: ["cre"], type: "group", + summary: "Create a z/OSMF workflow on a z/OS system", description: "Create a z/OSMF workflow on a z/OS system.", children: [ DataSet, diff --git a/packages/cli/src/workflows/create/dataset/Dataset.definition.ts b/packages/cli/src/workflows/create/dataset/Dataset.definition.ts index 65c51b1d1a..595ca321ee 100644 --- a/packages/cli/src/workflows/create/dataset/Dataset.definition.ts +++ b/packages/cli/src/workflows/create/dataset/Dataset.definition.ts @@ -22,7 +22,8 @@ import { join } from "path"; export const DataSet: ICommandDefinition = { name: "workflow-from-data-set", aliases: ["wfds"], - description: "Create a z/OSMF workflow on a z/OS system using a Data set", + summary: "Create a z/OSMF workflow on a z/OS system using a data set", + description: "Create a z/OSMF workflow on a z/OS system using a data set.", type: "command", handler: join(__dirname, "../Create.common.handler"), profile: { @@ -36,7 +37,7 @@ export const DataSet: ICommandDefinition = { required: true } ], - options: ([ + options: [ CreateCommonOptions.dataSet, CreateCommonOptions.systemName, CreateCommonOptions.owner, @@ -47,7 +48,7 @@ export const DataSet: ICommandDefinition = { CreateCommonOptions.deleteCompleted, CreateCommonOptions.overwrite // CreateCommonOptions.zosmfVersion - ]), + ], outputFormatOptions: true, examples: [ { diff --git a/packages/cli/src/workflows/create/localfile/LocalFile.definition.ts b/packages/cli/src/workflows/create/localfile/LocalFile.definition.ts index 365da73e09..aa70fb96d9 100644 --- a/packages/cli/src/workflows/create/localfile/LocalFile.definition.ts +++ b/packages/cli/src/workflows/create/localfile/LocalFile.definition.ts @@ -23,7 +23,8 @@ import { join } from "path"; export const LocalFile: ICommandDefinition = { name: "workflow-from-local-file", aliases: ["wflf"], - description: "Create a z/OSMF workflow on a z/OS system using a Local file", + summary: "Create a z/OSMF workflow on a z/OS system using a local file", + description: "Create a z/OSMF workflow on a z/OS system using a local file.", type: "command", handler: join(__dirname, "../Create.common.handler"), profile: { @@ -37,7 +38,7 @@ export const LocalFile: ICommandDefinition = { required: true } ], - options: ([ + options: [ CreateCommonOptions.localFile, CreateCommonOptions.systemName, CreateCommonOptions.owner, @@ -49,7 +50,7 @@ export const LocalFile: ICommandDefinition = { CreateCommonOptions.overwrite, CreateCommonOptions.remoteDirectory, CreateCommonOptions.keepFiles - ]), + ], outputFormatOptions: true, examples: [ { diff --git a/packages/cli/src/workflows/create/ussfile/UssFile.definition.ts b/packages/cli/src/workflows/create/ussfile/UssFile.definition.ts index 36fab40237..608810979b 100644 --- a/packages/cli/src/workflows/create/ussfile/UssFile.definition.ts +++ b/packages/cli/src/workflows/create/ussfile/UssFile.definition.ts @@ -22,7 +22,8 @@ import { join } from "path"; export const UssFile: ICommandDefinition = { name: "workflow-from-uss-file", aliases: ["wfuf"], - description: "Create a workflow instance in z/OSMF using a USS file", + summary: "Create a workflow instance in z/OSMF using a USS file", + description: "Create a workflow instance in z/OSMF using a USS file.", type: "command", handler: join(__dirname, "../Create.common.handler"), profile: { @@ -36,7 +37,7 @@ export const UssFile: ICommandDefinition = { required: true } ], - options: ([ + options: [ CreateCommonOptions.ussFile, CreateCommonOptions.systemName, CreateCommonOptions.owner, @@ -47,7 +48,7 @@ export const UssFile: ICommandDefinition = { CreateCommonOptions.deleteCompleted, CreateCommonOptions.overwrite // CreateCommonOptions.zosmfVersion - ]), + ], outputFormatOptions: true, examples: [ { diff --git a/packages/cli/src/workflows/delete/Delete.archived.common.handler.ts b/packages/cli/src/workflows/delete/Delete.archived.common.handler.ts index 6ef69e1908..e21a6427e5 100644 --- a/packages/cli/src/workflows/delete/Delete.archived.common.handler.ts +++ b/packages/cli/src/workflows/delete/Delete.archived.common.handler.ts @@ -17,7 +17,7 @@ import { ArchivedDeleteWorkflow } from "@zowe/zos-workflows-for-zowe-sdk"; import { ZosmfBaseHandler } from "@zowe/zosmf-for-zowe-sdk"; -const minimatch = require("minimatch"); +import { minimatch } from "minimatch"; /** * Common handler to delete a workflow instance in z/OSMF. @@ -39,7 +39,7 @@ export default class DeleteArchivedCommonHandler extends ZosmfBaseHandler { * @memberof DeleteArchivedCommonHandler */ public async processCmd(params: IHandlerParameters): Promise { - let error: string; + let error: ImperativeError; let listWorkflows: IArchivedWorkflows; this.arguments = params.arguments; @@ -58,7 +58,11 @@ export default class DeleteArchivedCommonHandler extends ZosmfBaseHandler { this.arguments.workflowKey ); } catch (err) { - error = "Delete workflow: " + err; + error = new ImperativeError({ + msg: "Delete workflow: " + err, + causeErrors: err.causeErrors, + additionalDetails: err.additionalDetails + }); throw error; } params.response.data.setObj("Deleted."); @@ -72,10 +76,10 @@ export default class DeleteArchivedCommonHandler extends ZosmfBaseHandler { const successWfs: IWorkflowsInfo[] = []; const failedWfs: IWorkflowsInfo[] = []; this.arguments.workflowName.includes(".*") - ? (normalized = this.arguments.workflowName + ? normalized = this.arguments.workflowName .split(".*") - .join("*")) - : (wildCard = false); + .join("*") + : wildCard = false; listWorkflows = await ListArchivedWorkflows.listArchivedWorkflows( this.mSession @@ -88,14 +92,14 @@ export default class DeleteArchivedCommonHandler extends ZosmfBaseHandler { ) { // Swap between checks to avoid "glob pattern string required" error. wildCard - ? (check = minimatch( + ? check = minimatch( listWorkflows.archivedWorkflows[i].workflowName, normalized - )) - : (check = + ) + : check = listWorkflows.archivedWorkflows[i] .workflowName === - this.arguments.workflowName); + this.arguments.workflowName; if (check) { try { diff --git a/packages/cli/src/workflows/delete/Delete.common.handler.ts b/packages/cli/src/workflows/delete/Delete.common.handler.ts index bcd1ba8b5e..1e6e29d131 100644 --- a/packages/cli/src/workflows/delete/Delete.common.handler.ts +++ b/packages/cli/src/workflows/delete/Delete.common.handler.ts @@ -49,7 +49,11 @@ export default class DeleteCommonHandler extends ZosmfBaseHandler { try{ await DeleteWorkflow.deleteWorkflow(this.mSession, this.arguments.workflowKey); } catch (err){ - error = "Delete workflow: " + err; + error = new ImperativeError({ + msg: "Delete workflow: " + err, + causeErrors: err.causeErrors, + additionalDetails: err.additionalDetails + }); throw error; } params.response.data.setObj("Deleted."); diff --git a/packages/cli/src/workflows/delete/Delete.definition.ts b/packages/cli/src/workflows/delete/Delete.definition.ts index 1e90e955aa..a7288bd55a 100644 --- a/packages/cli/src/workflows/delete/Delete.definition.ts +++ b/packages/cli/src/workflows/delete/Delete.definition.ts @@ -24,6 +24,7 @@ export const DeleteDefinition: ICommandDefinition = { name: "delete", aliases: ["del"], type: "group", + summary: "Delete an active workflow or an archived workflow from z/OSMF", description: "Delete an active workflow or an archived workflow from z/OSMF.", children: [ DeleteActiveWorkflow, diff --git a/packages/cli/src/workflows/delete/deleteActiveWorkflow/DeleteActiveWorkflow.definition.ts b/packages/cli/src/workflows/delete/deleteActiveWorkflow/DeleteActiveWorkflow.definition.ts index 07392f7fcd..c257f4e814 100644 --- a/packages/cli/src/workflows/delete/deleteActiveWorkflow/DeleteActiveWorkflow.definition.ts +++ b/packages/cli/src/workflows/delete/deleteActiveWorkflow/DeleteActiveWorkflow.definition.ts @@ -23,17 +23,18 @@ import { DeleteWorkflowOptions } from "../deleteActiveWorkflow/DeleteActiveWorkf export const DeleteActiveWorkflow: ICommandDefinition = { name: "active-workflow", aliases: ["aw"], - description: "Delete an active workflow instance in z/OSMF", + summary: "Delete an active workflow instance in z/OSMF", + description: "Delete an active workflow instance in z/OSMF.", type: "command", handler: join(__dirname, "../Delete.common.handler"), profile: { optional: ["zosmf"] }, - options: ([ + options: [ DeleteWorkflowOptions.workflowKey, DeleteWorkflowOptions.workflowName - ]), + ], examples: [ { description: "To delete a workflow instance in z/OSMF with workflow key \"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\"", diff --git a/packages/cli/src/workflows/delete/deleteArchivedWorkflow/DeleteArchivedWorkflow.definition.ts b/packages/cli/src/workflows/delete/deleteArchivedWorkflow/DeleteArchivedWorkflow.definition.ts index c53a8b2842..52a04d03d4 100644 --- a/packages/cli/src/workflows/delete/deleteArchivedWorkflow/DeleteArchivedWorkflow.definition.ts +++ b/packages/cli/src/workflows/delete/deleteArchivedWorkflow/DeleteArchivedWorkflow.definition.ts @@ -23,17 +23,18 @@ import { DeleteArchivedWorkflowOptions } from "../deleteArchivedWorkflow/DeleteA export const DeleteArchivedWorkflow: ICommandDefinition = { name: "archived-workflow", aliases: ["arw"], - description: "Delete an archived workflow from z/OSMF", + summary: "Delete an archived workflow from z/OSMF", + description: "Delete an archived workflow from z/OSMF.", type: "command", handler: join(__dirname, "../Delete.archived.common.handler"), profile: { optional: ["zosmf"] }, - options: ([ + options: [ DeleteArchivedWorkflowOptions.workflowKey, DeleteArchivedWorkflowOptions.workflowName - ]), + ], examples: [ { description: "To delete an archived workflow from z/OSMF with workflow key \"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\"", diff --git a/packages/cli/src/workflows/list/List.definition.ts b/packages/cli/src/workflows/list/List.definition.ts index 77ca57d553..6c35a0fdb5 100644 --- a/packages/cli/src/workflows/list/List.definition.ts +++ b/packages/cli/src/workflows/list/List.definition.ts @@ -26,6 +26,7 @@ export const ListDefinition: ICommandDefinition = { name: "list", aliases: ["ls"], type: "group", + summary: "List the z/OSMF workflows for a system or a sysplex with filter options", description: "List the z/OSMF workflows for a system or a sysplex with filter options.", children: [ ActiveWorkflows, diff --git a/packages/cli/src/workflows/list/activeWorkflowDetails/ActiveWorkflowDetails.definition.ts b/packages/cli/src/workflows/list/activeWorkflowDetails/ActiveWorkflowDetails.definition.ts index d16c4109c5..c4e4a2eaee 100644 --- a/packages/cli/src/workflows/list/activeWorkflowDetails/ActiveWorkflowDetails.definition.ts +++ b/packages/cli/src/workflows/list/activeWorkflowDetails/ActiveWorkflowDetails.definition.ts @@ -22,20 +22,21 @@ import { join } from "path"; export const ActiveWorkflowDetails: ICommandDefinition = { name: "active-workflow-details", aliases: ["awd"], - description: "Get the details of an active z/OSMF workflow", + summary: "Get the details of an active z/OSMF workflow", + description: "Get the details of an active z/OSMF workflow.", type: "command", handler: join(__dirname, "./ActiveWorkflowDetails.handler"), profile: { optional: ["zosmf"] }, - options: ([ + options: [ ActiveWorkflowDetailsCommonOptions.workflowName, ActiveWorkflowDetailsCommonOptions.workflowKey, ActiveWorkflowDetailsCommonOptions.listSteps, ActiveWorkflowDetailsCommonOptions.stepsSummaryOnly, ActiveWorkflowDetailsCommonOptions.listVariables, ActiveWorkflowDetailsCommonOptions.skipWorkflowSummary - ]), + ], examples: [ { description: "To list the details of an active workflow with key \"7c62c790-0340-86b2-61ce618d8f8c\" including its steps and variables", diff --git a/packages/cli/src/workflows/list/activeWorkflowDetails/ActiveWorkflowDetails.handler.ts b/packages/cli/src/workflows/list/activeWorkflowDetails/ActiveWorkflowDetails.handler.ts index 4364ca9b6e..9cbc425a25 100644 --- a/packages/cli/src/workflows/list/activeWorkflowDetails/ActiveWorkflowDetails.handler.ts +++ b/packages/cli/src/workflows/list/activeWorkflowDetails/ActiveWorkflowDetails.handler.ts @@ -65,7 +65,11 @@ export default class ActiveWorkflowDetails extends ZosmfBaseHandler { stepSummaries = response.steps; } } catch(err){ - error = "List workflow details error: " + err; + error = new ImperativeError({ + msg: "List workflow details error: " + err, + causeErrors: err.causeErrors, + additionalDetails: err.additionalDetails + }); throw error; } params.response.data.setObj(response); diff --git a/packages/cli/src/workflows/list/activeWorkflows/ActiveWorkflows.definition.ts b/packages/cli/src/workflows/list/activeWorkflows/ActiveWorkflows.definition.ts index 6e8aa6c28c..75220eec8e 100644 --- a/packages/cli/src/workflows/list/activeWorkflows/ActiveWorkflows.definition.ts +++ b/packages/cli/src/workflows/list/activeWorkflows/ActiveWorkflows.definition.ts @@ -23,23 +23,23 @@ import { join } from "path"; export const ActiveWorkflows: ICommandDefinition = { name: "active-workflows", aliases: ["aw"], - summary: "List active workflow instance(s) in z/OSMF.", + summary: "List active workflow instance(s) in z/OSMF", description: "List active workflow instance(s) in z/OSMF.\n" + "Multiple filters can be used together.\n" + - "Omitting all options will list all workflows on the sysplex", + "Omitting all options will list all workflows on the sysplex.", type: "command", handler: join(__dirname, "ActiveWorkflows.handler"), profile: { optional: ["zosmf"] }, - options: ([ + options: [ ListActiveWorkflowsOptions.workflowName, ListActiveWorkflowsOptions.category, ListActiveWorkflowsOptions.system, ListActiveWorkflowsOptions.owner, ListActiveWorkflowsOptions.vendor, ListActiveWorkflowsOptions.statusName - ]), + ], outputFormatOptions: true, examples: [ { diff --git a/packages/cli/src/workflows/list/activeWorkflows/ActiveWorkflows.handler.ts b/packages/cli/src/workflows/list/activeWorkflows/ActiveWorkflows.handler.ts index 49e1113f3b..37140be7c1 100644 --- a/packages/cli/src/workflows/list/activeWorkflows/ActiveWorkflows.handler.ts +++ b/packages/cli/src/workflows/list/activeWorkflows/ActiveWorkflows.handler.ts @@ -9,7 +9,7 @@ * */ -import { IHandlerParameters, TextUtils } from "@zowe/imperative"; +import { IHandlerParameters, ImperativeError, TextUtils } from "@zowe/imperative"; import { IWorkflowsInfo, ListWorkflows, IActiveWorkflows } from "@zowe/zos-workflows-for-zowe-sdk"; import { ZosmfBaseHandler } from "@zowe/zosmf-for-zowe-sdk"; @@ -47,7 +47,11 @@ export default class ListActiveWorkflowsHandler extends ZosmfBaseHandler { statusName: this.arguments.statusName }); } catch (err) { - error = "List workflow(s) " + err; + error = new ImperativeError({ + msg: "List workflow(s) " + err, + causeErrors: err.causeErrors, + additionalDetails: err.additionalDetails + }); throw error; } diff --git a/packages/cli/src/workflows/list/archivedWorkflows/ArchivedWorkflows.definition.ts b/packages/cli/src/workflows/list/archivedWorkflows/ArchivedWorkflows.definition.ts index 3eef2605f0..a1cb40b173 100644 --- a/packages/cli/src/workflows/list/archivedWorkflows/ArchivedWorkflows.definition.ts +++ b/packages/cli/src/workflows/list/archivedWorkflows/ArchivedWorkflows.definition.ts @@ -21,7 +21,7 @@ import { join } from "path"; export const ArchivedWorkflows: ICommandDefinition = { name: "archived-workflows", aliases: ["arw"], - summary: "List all archived workflows for a system.", + summary: "List all archived workflows for a system", description: "List the archived z/OSMF workflows for a system or sysplex.", type: "command", handler: join(__dirname, "ArchivedWorkflows.handler"), diff --git a/packages/cli/src/workflows/list/archivedWorkflows/ArchivedWorkflows.handler.ts b/packages/cli/src/workflows/list/archivedWorkflows/ArchivedWorkflows.handler.ts index 55b1e752cf..e411ff9374 100644 --- a/packages/cli/src/workflows/list/archivedWorkflows/ArchivedWorkflows.handler.ts +++ b/packages/cli/src/workflows/list/archivedWorkflows/ArchivedWorkflows.handler.ts @@ -9,7 +9,7 @@ * */ -import { IHandlerParameters, TextUtils } from "@zowe/imperative"; +import { IHandlerParameters, ImperativeError, TextUtils } from "@zowe/imperative"; import { ListArchivedWorkflows, IWorkflowsInfo, IArchivedWorkflows } from "@zowe/zos-workflows-for-zowe-sdk"; import { ZosmfBaseHandler } from "@zowe/zosmf-for-zowe-sdk"; @@ -40,7 +40,11 @@ export default class ListArchivedWorkflowsHandler extends ZosmfBaseHandler { response = await ListArchivedWorkflows.listArchivedWorkflows( this.mSession); } catch (err) { - error = "List workflow(s) " + err; + error = new ImperativeError({ + msg: "List workflow(s) " + err, + causeErrors: err.causeErrors, + additionalDetails: err.additionalDetails + }); throw error; } commandParameters.response.data.setObj(response); diff --git a/packages/cli/src/workflows/list/retrieveWorkflowDefinition/RetrieveWorkflowDefinition.definition.ts b/packages/cli/src/workflows/list/retrieveWorkflowDefinition/RetrieveWorkflowDefinition.definition.ts index f58c89135f..b118f02dcd 100644 --- a/packages/cli/src/workflows/list/retrieveWorkflowDefinition/RetrieveWorkflowDefinition.definition.ts +++ b/packages/cli/src/workflows/list/retrieveWorkflowDefinition/RetrieveWorkflowDefinition.definition.ts @@ -22,6 +22,7 @@ import { join } from "path"; export const RetrieveWorkflowDefinition: ICommandDefinition = { name: "definition-file-details", aliases: ["dfd"], + summary: "Retrieve the contents of a z/OSMF workflow definition from a z/OS system", description: "Retrieve the contents of a z/OSMF workflow definition from a z/OS system.", type: "command", handler: join(__dirname, "./RetrieveWorkflowDefinition.handler"), @@ -37,10 +38,10 @@ export const RetrieveWorkflowDefinition: ICommandDefinition = { required: true } ], - options: ([ + options: [ RetrieveWorkflowDefinitionCommonOptions.listSteps, RetrieveWorkflowDefinitionCommonOptions.listVariables - ]), + ], examples: [ { description: "To list the contents of a workflow definition stored in the UNIX file \"/user/dir/workflow.xml\"" + diff --git a/packages/cli/src/workflows/list/retrieveWorkflowDefinition/RetrieveWorkflowDefinition.handler.ts b/packages/cli/src/workflows/list/retrieveWorkflowDefinition/RetrieveWorkflowDefinition.handler.ts index 7bac0f9f26..5fbdf12448 100644 --- a/packages/cli/src/workflows/list/retrieveWorkflowDefinition/RetrieveWorkflowDefinition.handler.ts +++ b/packages/cli/src/workflows/list/retrieveWorkflowDefinition/RetrieveWorkflowDefinition.handler.ts @@ -9,7 +9,7 @@ * */ -import { IHandlerParameters } from "@zowe/imperative"; +import { IHandlerParameters, ImperativeError } from "@zowe/imperative"; import { DefinitionWorkflow, IWorkflowDefinition } from "@zowe/zos-workflows-for-zowe-sdk"; import { ZosmfBaseHandler } from "@zowe/zosmf-for-zowe-sdk"; @@ -41,7 +41,11 @@ export default class ListActiveWorkflowsHandler extends ZosmfBaseHandler { this.mSession, undefined, this.arguments.definitionFilePath, this.arguments.listSteps, this.arguments.listVariables); } catch (err) { - error = "List workflow(s) " + err; + error = new ImperativeError({ + msg: "List workflow(s) " + err, + causeErrors: err.causeErrors, + additionalDetails: err.additionalDetails + }); throw error; } diff --git a/packages/cli/src/workflows/start/Start.definition.ts b/packages/cli/src/workflows/start/Start.definition.ts index 9de5c35a42..f082ee65a1 100644 --- a/packages/cli/src/workflows/start/Start.definition.ts +++ b/packages/cli/src/workflows/start/Start.definition.ts @@ -24,6 +24,7 @@ export const StartDefinition: ICommandDefinition = { name: "start", aliases: ["sta"], type: "group", + summary: "Start a z/OSMF workflow on a z/OS system", description: "Start a z/OSMF workflow on a z/OS system.", children: [ WorkflowFull, diff --git a/packages/cli/src/workflows/start/workflowFull/WorkflowFull.definition.ts b/packages/cli/src/workflows/start/workflowFull/WorkflowFull.definition.ts index 31b0b140de..757da41b5b 100644 --- a/packages/cli/src/workflows/start/workflowFull/WorkflowFull.definition.ts +++ b/packages/cli/src/workflows/start/workflowFull/WorkflowFull.definition.ts @@ -23,19 +23,20 @@ import { StartCommonOptions } from "../Start.common.options"; export const WorkflowFull: ICommandDefinition = { name: "workflow-full", aliases: ["wf"], + summary: "Will run workflow from the beginning to the end or to the first manual step", description: "Will run workflow from the beginning to the end or to the first manual step.", type: "command", handler: join(__dirname, "./WorkflowFull.handler"), profile: { optional: ["zosmf"] }, - options: ([ + options: [ StartCommonOptions.workflowKey, StartCommonOptions.workflowName, StartCommonOptions.resolveConflict, StartCommonOptions.wait // StartCommonOptions.zosmfVersion, - ]), + ], examples: [ { description: "To start a workflow instance in z/OSMF with workflow key \"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\"", diff --git a/packages/cli/src/workflows/start/workflowFull/WorkflowFull.handler.ts b/packages/cli/src/workflows/start/workflowFull/WorkflowFull.handler.ts index 85aa5eff50..7e58d468d9 100644 --- a/packages/cli/src/workflows/start/workflowFull/WorkflowFull.handler.ts +++ b/packages/cli/src/workflows/start/workflowFull/WorkflowFull.handler.ts @@ -52,7 +52,11 @@ export default class WorkflowFullHandler extends ZosmfBaseHandler { try{ await StartWorkflow.startWorkflow(this.mSession, workflowKey, this.arguments.resolveConflict); } catch (err) { - error = "Start workflow: " + err; + error = new ImperativeError({ + msg: "Start workflow: " + err, + causeErrors: err.causeErrors, + additionalDetails: err.additionalDetails + }); throw error; } diff --git a/packages/cli/src/workflows/start/workflowStep/WorkflowStep.definition.ts b/packages/cli/src/workflows/start/workflowStep/WorkflowStep.definition.ts index dbd6aedbd0..888c6a37a5 100644 --- a/packages/cli/src/workflows/start/workflowStep/WorkflowStep.definition.ts +++ b/packages/cli/src/workflows/start/workflowStep/WorkflowStep.definition.ts @@ -23,6 +23,7 @@ import { StartCommonOptions } from "../Start.common.options"; export const WorkflowStep: ICommandDefinition = { name: "workflow-step", aliases: ["ws"], + summary: "Will run given step of workflow instance plus following steps if specified by --perform-following-steps option", description: "Will run given step of workflow instance plus following steps if specified by --perform-following-steps option.", type: "command", handler: join(__dirname, "./WorkflowStep.handler"), @@ -37,13 +38,13 @@ export const WorkflowStep: ICommandDefinition = { required: true } ], - options: ([ + options: [ StartCommonOptions.workflowKey, StartCommonOptions.workflowName, StartCommonOptions.resolveConflict, StartCommonOptions.performFollowingSteps // StartCommonOptions.zosmfVersion, - ]), + ], examples: [ { description: "To start step \"Step1\" only in a workflow instance in z/OSMF with workflow key \"d043b5f1-adab-48e7-b7c3-d41cd95fa4b0\"", diff --git a/packages/cli/src/workflows/start/workflowStep/WorkflowStep.handler.ts b/packages/cli/src/workflows/start/workflowStep/WorkflowStep.handler.ts index 6757fb6f4a..25ba4b7711 100644 --- a/packages/cli/src/workflows/start/workflowStep/WorkflowStep.handler.ts +++ b/packages/cli/src/workflows/start/workflowStep/WorkflowStep.handler.ts @@ -50,7 +50,11 @@ export default class WorkflowStepHandler extends ZosmfBaseHandler { await StartWorkflow.startWorkflow(this.mSession, this.arguments.workflowKey, this.arguments.resolveConflict, this.arguments.stepName, this.arguments.performFollowingSteps); } catch (err){ - error = "Start workflow: " + err; + error = new ImperativeError({ + msg: "Start workflow: " + err, + causeErrors: err.causeErrors, + additionalDetails: err.additionalDetails + }); throw error; } params.response.data.setObj("Started."); @@ -68,7 +72,11 @@ export default class WorkflowStepHandler extends ZosmfBaseHandler { await StartWorkflow.startWorkflow(this.mSession, getWfKey, this.arguments.resolveConflict, this.arguments.stepName, this.arguments.performFollowingSteps); } catch (err){ - error = "Start workflow: " + err; + error = new ImperativeError({ + msg: "Start workflow Error: " + err, + causeErrors: err.causeErrors, + additionalDetails: err.additionalDetails + }); throw error; } params.response.data.setObj("Started."); diff --git a/packages/cli/src/zosconsole/issue/command/Command.handler.ts b/packages/cli/src/zosconsole/issue/command/Command.handler.ts index 45e8d093d0..a2f981fe4e 100644 --- a/packages/cli/src/zosconsole/issue/command/Command.handler.ts +++ b/packages/cli/src/zosconsole/issue/command/Command.handler.ts @@ -57,7 +57,7 @@ export default class Handler extends ZosmfBaseHandler { responseKey: response.lastResponseKey, cmdResponseUrl: response.cmdResponseUrl || undefined, keywordDetected: response.keywordDetected || - ((!(commandParameters.arguments["solicited-keyword"] == null)) ? false : undefined) + (commandParameters.arguments["solicited-keyword"] != null ? false : undefined) }; commandParameters.response.console.log("Additional details:"); commandParameters.response.console.log("-------------------"); diff --git a/packages/cli/src/zosfiles/-strings-/en.ts b/packages/cli/src/zosfiles/-strings-/en.ts index 461c0b0274..fbe4e64b12 100644 --- a/packages/cli/src/zosfiles/-strings-/en.ts +++ b/packages/cli/src/zosfiles/-strings-/en.ts @@ -20,31 +20,36 @@ export default { WITH_VALUE: "with value" }, CREATE: { + SUMMARY: "Create data sets", DESCRIPTION: "Create data sets.", ACTIONS: { DATA_SET_BINARY: { - DESCRIPTION: "Create executable data sets", + SUMMARY: "Create executable data sets", + DESCRIPTION: "Create executable data sets.", EXAMPLES: { EX1: "Create an empty binary partitioned data set (PDS) with default parameters", EX2: "Create an empty binary PDSE using data set type LIBRARY" } }, DATA_SET_CLASSIC: { - DESCRIPTION: "Create classic data sets (JCL, HLASM, CBL, etc...)", + SUMMARY: "Create classic data sets (JCL, HLASM, CBL, etc...)", + DESCRIPTION: "Create classic data sets (JCL, HLASM, CBL, etc...).", EXAMPLES: { EX1: "Create an empty z/OS 'classic' PDS with default parameters", EX2: `Create an empty z/OS 'classic' PDSE using data set type LIBRARY` } }, DATA_SET_C: { - DESCRIPTION: "Create data sets for C code programming", + SUMMARY: "Create data sets for C code programming", + DESCRIPTION: "Create data sets for C code programming.", EXAMPLES: { EX1: "Create an empty C code PDS with default parameters", EX2: "Create an empty C code PDSE using data set type LIBRARY" } }, DATA_SET_LIKE: { - DESCRIPTION: "Create data sets based on the properties of an existing data set", + SUMMARY: "Create data sets based on the properties of an existing data set", + DESCRIPTION: "Create data sets based on the properties of an existing data set.", EXAMPLES: { EX1: "Create a data set with default parameters and like flag", EX2: "Create a data set with default parameters and like flag and lrecl flag", @@ -52,22 +57,25 @@ export default { } }, DATA_SET_PARTITIONED: { - DESCRIPTION: "Create partitioned data sets (PDS)", + SUMMARY: "Create partitioned data sets (PDS)", + DESCRIPTION: "Create partitioned data sets (PDS).", EXAMPLES: { EX1: "Create an empty PDS with default parameters", EX2: "Create an empty PDSE using data set type LIBRARY" } }, DATA_SET_SEQUENTIAL: { - DESCRIPTION: "Create physical sequential data sets (PS)", + SUMMARY: "Create physical sequential data sets (PS)", + DESCRIPTION: "Create physical sequential data sets (PS).", EXAMPLES: { EX1: "Create an empty physical sequential data set with default parameters" } }, VSAM: { - DESCRIPTION: "Create a VSAM cluster", + SUMMARY: "Create a VSAM cluster", + DESCRIPTION: "Create a VSAM cluster.", POSITIONALS: { - DATASETNAME: "The name of the dataset in which to create a VSAM cluster" + DATASETNAME: "The name of the data set in which to create a VSAM cluster" }, OPTIONS: { RETAINFOR: "The number of days that the VSAM cluster will be retained on the system. You can delete the cluster at any " + @@ -176,16 +184,18 @@ export default { } }, COPY: { + SUMMARY: "Copy a data set", DESCRIPTION: "Copy a data set.", ACTIONS: { DATA_SET: { - DESCRIPTION: "Copy a data set to another data set", + SUMMARY: "Copy a data set to another data set", + DESCRIPTION: "Copy a data set to another data set.", POSITIONALS: { FROMDSNAME: "The name of the data set that you want to copy from", TODSNAME: "The name of the data set that you want to copy to (data set must be preallocated)" }, OPTIONS: { - REPLACE: "Specify this option as true if you wish to replace like-named members in the target dataset" + REPLACE: "Specify this option as true if you wish to replace like-named members in the target data set" }, EXAMPLES: { EX1: "Copy the data set named 'USER.FROM.SET' to the data set named 'USER.TO.SET'", @@ -196,21 +206,22 @@ export default { } }, DATA_SET_CROSS_LPAR: { - DESCRIPTION: "Copy a data set to another data set on a specified LPAR", + SUMMARY: "Copy a data set to another data set on a specified LPAR", + DESCRIPTION: "Copy a data set to another data set on a specified LPAR.", POSITIONALS: { FROMDSNAME: "The name of the data set that you want to copy from", - TODSNAME: "The name of the data set that you want to copy to. If the dataset does not " + + TODSNAME: "The name of the data set that you want to copy to. If the data set does not " + "exist it will be allocated automatically" }, OPTIONS: { - REPLACE: "Specify this option as true if you wish to replace the target dataset if it already exists", + REPLACE: "Specify this option as true if you wish to replace the target data set if it already exists.", TARGETHOST: "The target z/OSMF server host name.", TARGETPORT: "The target z/OSMF server port.", TARGETUSER: "The target z/OSMF user name, which can be the same as your TSO login.", TARGETPASS: "The target z/OSMF password, which can be the same as your TSO password.", TARGETTOKENVAL: "The type of token to get and use for the API for the target system.", TARGETTOKENTYPE: "The value of the token to pass to the API for the target system.", - TARGETPROFILE: "The name of a z/OSMF profile to load for the target host. ", + TARGETPROFILE: "The name of a z/OSMF profile to load for the target host.", TARGETVOLSER: "The volume serial (VOLSER) on which you want the target data set to be placed.", TARGETMGTCLS: "The SMS management class to use for the allocation of the target data set.", TARGETDATACLS: "The SMS data class to use for the allocation of the target data set.", @@ -228,10 +239,12 @@ export default { } }, DELETE: { + SUMMARY: "Delete a data set or Unix System Services file", DESCRIPTION: "Delete a data set or Unix System Services file.", ACTIONS: { DATA_SET: { - DESCRIPTION: "Delete a data set or data set member permanently", + SUMMARY: "Delete a data set or data set member permanently", + DESCRIPTION: "Delete a data set or data set member permanently.", POSITIONALS: { DSNAME: "The name of the data set that you want to delete" }, @@ -246,6 +259,7 @@ export default { } }, MIGRATED_DATA_SET: { + SUMMARY: "Delete migrated data sets", DESCRIPTION: "Delete migrated data sets.", POSITIONALS: { DATASETNAME: "The name of the migrated data set you want to delete." @@ -260,7 +274,8 @@ export default { } }, VSAM: { - DESCRIPTION: "Delete a VSAM cluster permanently", + SUMMARY: "Delete a VSAM cluster permanently", + DESCRIPTION: "Delete a VSAM cluster permanently.", POSITIONALS: { DSNAME: "The name of the VSAM cluster that you want to delete" }, @@ -278,7 +293,8 @@ export default { } }, USS: { - DESCRIPTION: "Delete a Unix Systems Services (USS) File or directory permanently", + SUMMARY: "Delete a Unix Systems Services (USS) file or directory permanently", + DESCRIPTION: "Delete a Unix Systems Services (USS) file or directory permanently.", POSITIONALS: { FILENAME: "The name of the file or directory that you want to delete" }, @@ -313,7 +329,7 @@ export default { ACTIONS: { ALL_MEMBERS: { SUMMARY: "Download all members from a pds", - DESCRIPTION: "Download all members from a partitioned data set to a local folder", + DESCRIPTION: "Download all members from a partitioned data set to a local folder.", POSITIONALS: { DATASETNAME: "The name of the data set from which you want to download members" }, @@ -324,7 +340,7 @@ export default { }, DATA_SET: { SUMMARY: "Download content from a z/OS data set", - DESCRIPTION: "Download content from a z/OS data set to a local file", + DESCRIPTION: "Download content from a z/OS data set to a local file.", POSITIONALS: { DATASETNAME: "The name of the data set that you want to download" }, @@ -334,7 +350,7 @@ export default { }, USS_FILE: { SUMMARY: "Download content from a USS file", - DESCRIPTION: "Download content from a USS file to a local file on your PC", + DESCRIPTION: "Download content from a USS file to a local file on your PC.", POSITIONALS: { USSFILENAME: "The name of the USS file you want to download" }, @@ -345,7 +361,7 @@ export default { }, USS_DIR: { SUMMARY: "Download content from a USS directory", - DESCRIPTION: "Download content from a USS directory to a local directory on your PC", + DESCRIPTION: "Download content from a USS directory to a local directory on your PC.", POSITIONALS: { USSDIRNAME: "The name of the USS directory you want to download" }, @@ -369,7 +385,7 @@ export default { `(e.g. "ibmuser.j*.old" matches "ibmuser.jcl.old" but not "ibmuser.jcl.very.old") ${TextUtils.chalk.yellow("**")}: matches any number of characters within any number of data set name qualifiers ` + `(e.g. "ibmuser.**.old" matches both "ibmuser.jcl.old" and "ibmuser.jcl.very.old") - However, the pattern cannot begin with any of these sequences.You can specify multiple patterns separated by commas, ` + + However, the pattern cannot begin with any of these sequences. You can specify multiple patterns separated by commas, ` + `for example "ibmuser.**.cntl,ibmuser.**.jcl"` }, EXAMPLES: { @@ -381,7 +397,7 @@ export default { } }, OPTIONS: { - ATTRIBUTES: "Path of an attributes file to control how files are downloaded", + ATTRIBUTES: "Path of an attributes file to control how files are downloaded.", VOLUME: "The volume serial (VOLSER) where the data set resides. You can use this option at any time. However, the VOLSER is required " + "only when the data set is not cataloged on the system. A VOLSER is analogous to a drive name on a PC.", BINARY: "Download the file content in binary mode, which means that no data conversion is performed. The data transfer process " + @@ -391,7 +407,7 @@ export default { " Conflicts with binary.", ENCODING: "Download the file content with encoding mode, which means that data conversion is performed using the file encoding " + "specified.", - FAIL_FAST: "Set this option to false to continue downloading dataset members if one or more fail.", + FAIL_FAST: "Set this option to false to continue downloading data set members if one or more fail.", FAIL_FAST_USS: "Set this option to false to continue downloading USS files if one or more fail.", FILE: "The path to the local file where you want to download the content. When you omit the option, the command generates a file " + "name automatically for you.", @@ -423,9 +439,9 @@ export default { "The maximum number of TSO address spaces have been created. When you specify 0, " + Constants.DISPLAY_NAME + " attempts to download all files at once" + " without a maximum number of concurrent requests. ", - PRESERVE_ORIGINAL_LETTER_CASE: "Specifies if the automatically generated directories and files use the original letter case", - INCLUDE_HIDDEN: "Include hidden files and folders that have names beginning with a dot", - OVERWRITE: "Overwrite files that already exist in your local environment" + PRESERVE_ORIGINAL_LETTER_CASE: "Specifies if the automatically generated directories and files use the original letter case.", + INCLUDE_HIDDEN: "Include hidden files and folders that have names beginning with a dot.", + OVERWRITE: "Overwrite files that already exist in your local environment." } }, INVOKE: { @@ -477,7 +493,7 @@ export default { }, DATA_SET: { SUMMARY: "List data sets", - DESCRIPTION: "List data sets that match a pattern in the data set name", + DESCRIPTION: "List data sets that match a pattern in the data set name.", POSITIONALS: { DATASETNAME: "The name or pattern of the data set that you want to list" }, @@ -491,7 +507,7 @@ export default { }, USS_FILE: { SUMMARY: "List USS files", - DESCRIPTION: "List USS files and directories in a UNIX file path", + DESCRIPTION: "List USS files and directories in a UNIX file path.", POSITIONALS: { PATH: "The directory containing the files and directories to be listed" }, @@ -570,6 +586,59 @@ export default { RESPONSETIMEOUT: "The maximum amount of time in seconds the z/OSMF Files TSO servlet should run before returning a response." + " Any request exceeding this amount of time will be terminated and return an error. Allowed values: 5 - 600" }, + SEARCH: { + SUMMARY: "Search Files", + DESCRIPTION: "Search files for a search term.", + ACTIONS: { + DS: { + SUMMARY: "Search Data Sets and PDS Members", + DESCRIPTION: "Search all data sets and PDS members that match the data set name for a search term.", + POSITIONALS: { + PATTERN: `The pattern to match data sets against. Also known as 'DSLEVEL'. The following special sequences can be ` + + `used in the pattern: + ${TextUtils.chalk.yellow("%")}: matches any single character + ${TextUtils.chalk.yellow("*")}: matches any number of characters within a data set name qualifier ` + + `(e.g. "ibmuser.j*.old" matches "ibmuser.jcl.old" but not "ibmuser.jcl.very.old") + ${TextUtils.chalk.yellow("**")}: matches any number of characters within any number of data set name qualifiers ` + + `(e.g. "ibmuser.**.old" matches both "ibmuser.jcl.old" and "ibmuser.jcl.very.old") + However, the pattern cannot begin with any of these sequences. You can specify multiple patterns separated by commas, ` + + `for example "ibmuser.**.cntl,ibmuser.**.jcl"` + }, + OPTIONS: { + CASESENSITIVE: "The search should be case sensitive", + MAINFRAMESEARCH: "Perform a preliminary search on the mainframe, reducing network traffic. However, this option " + + "does not work with data sets that contain binary data. This option should be omitted if any data sets may be in " + + "binary format. Failure to do so may result in an incomplete set of search results.", + MAX_CONCURRENT_REQUESTS: "Specifies the maximum number of concurrent z/OSMF REST API requests to search files. " + + "Increasing the value results in faster searches. " + + "However, increasing the value increases resource consumption on z/OS and can be prone " + + "to errors caused by making too many concurrent requests.", + TIMEOUT: "The number of seconds to search before timing out" + }, + EXAMPLES: { + EX1: { + DESCRIPTION: "Search all of IBMUSER's, data sets for 'ZOWE'", + OPTIONS: "'IBMUSER.*' 'ZOWE'" + }, + EX2: { + DESCRIPTION: "Search all of IBMUSER's, data sets for 'ZOWE' in uppercase only", + OPTIONS: "'IBMUSER.*' 'ZOWE' --case-sensitive" + }, + EX3: { + DESCRIPTION: "Search all of IBMUSER's, data sets for 'ZOWE', and time out in 1 minute", + OPTIONS: "'IBMUSER.*' 'ZOWE' --timeout 60" + }, + EX4: { + DESCRIPTION: "Search all of IBMUSER's, data sets for 'ZOWE', and perform 8 parallel tasks", + OPTIONS: "'IBMUSER.*' 'ZOWE' --max-concurrent-requests 8" + } + } + } + }, + OPTIONS: { + SEARCHSTRING: "The parameter to search for" + } + }, UNMOUNT: { SUMMARY: "Unmount file systems", DESCRIPTION: "Unmount file systems, such as HFS, ZFS, and more. This disconnects you from USS file systems.", @@ -587,10 +656,12 @@ export default { } }, UPLOAD: { + SUMMARY: "Upload the contents of a file to data sets", DESCRIPTION: "Upload the contents of a file to data sets.", ACTIONS: { DIR_TO_PDS: { - DESCRIPTION: "Upload files from a local directory to a partitioned data set (PDS)", + SUMMARY: "Upload files from a local directory to a partitioned data set (PDS)", + DESCRIPTION: "Upload files from a local directory to a partitioned data set (PDS).", POSITIONALS: { INPUTDIR: "The path for a local directory that you want to upload to a PDS", DATASETNAME: "The name of the partitioned data set to which you want to upload the files" @@ -601,7 +672,8 @@ export default { } }, FILE_TO_DATA_SET: { - DESCRIPTION: "Upload the contents of a file to a z/OS data set", + SUMMARY: "Upload the contents of a file to a z/OS data set", + DESCRIPTION: "Upload the contents of a file to a z/OS data set.", POSITIONALS: { INPUTFILE: "The local file that you want to upload to a data set", DATASETNAME: "The name of the data set to which you want to upload the file" @@ -613,7 +685,8 @@ export default { } }, STDIN_TO_DATA_SET: { - DESCRIPTION: "Upload the content of a stdin to a z/OS data set", + SUMMARY: "Upload the content of a stdin to a z/OS data set", + DESCRIPTION: "Upload the content of a stdin to a z/OS data set.", POSITIONALS: { DATASETNAME: "The name of the data set to which you want to upload data" }, @@ -624,7 +697,8 @@ export default { } }, FILE_TO_USS: { - DESCRIPTION: "Upload content to a USS file from local file", + SUMMARY: "Upload content to a USS file from local file", + DESCRIPTION: "Upload content to a USS file from local file.", POSITIONALS: { INPUTFILE: "The local file that you want to upload to a USS file", USSFILENAME: "The name of the USS file to which you want to upload the file" @@ -701,7 +775,7 @@ export default { "All files matching specified file names will be uploaded in ASCII mode. " + "If a .zosattributes file (or equivalent file specified via --attributes) is present, " + "--ascii-files will be ignored.", - ATTRIBUTES: "Path of an attributes file to control how files are uploaded", + ATTRIBUTES: "Path of an attributes file to control how files are uploaded.", MAX_CONCURRENT_REQUESTS: "Specifies the maximum number of concurrent z/OSMF REST API requests to upload files." + " Increasing the value results in faster uploads. " + "However, increasing the value increases resource consumption on z/OS and can be prone " + @@ -710,7 +784,7 @@ export default { "The maximum number of TSO address spaces have been created. When you specify 0, " + Constants.DISPLAY_NAME + " attempts to upload all members at once" + " without a maximum number of concurrent requests. ", - INCLUDE_HIDDEN: "Include hidden files and folders that have names beginning with a dot" + INCLUDE_HIDDEN: "Include hidden files and folders that have names beginning with a dot." } }, VIEW: { @@ -794,12 +868,12 @@ export default { } }, COMPARE: { - SUMMARY: "Compare the contents of a two data set members", - DESCRIPTION: "Compare the contents of a two data set members on your terminal (stdout).", + SUMMARY: "Compare the contents of z/OS data sets or USS files", + DESCRIPTION: "Compare the contents of z/OS data sets or USS files in your terminal (stdout).", ACTIONS: { DATA_SET: { - SUMMARY: "Compare content of two z/OS data sets", - DESCRIPTION: "Compare content of two z/OS data sets on your terminal (stdout).", + SUMMARY: "Compare the contents of two z/OS data sets", + DESCRIPTION: "Compare the contents of two z/OS data sets in your terminal (stdout).", POSITIONALS: { DATASETNAME1: "The name of the first data set you want to compare.", DATASETNAME2: "The name of the second data set you want to compare." @@ -810,73 +884,73 @@ export default { } }, LOCAL_FILE_DATA_SET: { - SUMMARY: "Compare content of a local file and a z/os dataset", - DESCRIPTION: "Compare content of a local file and a z/os dataset on your terminal (stdout).", + SUMMARY: "Compare the contents of a local file and a z/OS data set", + DESCRIPTION: "Compare the contents of a local file and a z/OS data set in your terminal (stdout).", POSITIONALS: { - LOCALFILEPATH: "The path of the local file you want to compare.", + LOCALFILEPATH: "The path of the local file you want to compare.", DATASETNAME: "The name of the data set you want to compare." }, EXAMPLES: { EX1: `Compare the contents of the local file and the data set member "./a.txt" and "sys1.samplib(antxtso)"`, - EX2: `Compare the contents of the local file and the data set member "./a.txt" and "sys1.samplib(antxtso)"` + + EX2: `Compare the contents of the local file and the data set member "./a.txt" and "sys1.samplib(antxtso)" ` + `without sequence numbers` } }, USS_FILE: { - SUMMARY: "Compare the contents of two z/os uss files", - DESCRIPTION: "Compare the contents of two uss files on your terminal (stdout). browser.", + SUMMARY: "Compare the contents of two z/OS USS files", + DESCRIPTION: "Compare the contents of two z/OS USS files in your terminal (stdout).", POSITIONALS: { - USSFILEPATH1: "The path of the first uss file you want to compare.", - USSFILEPATH2: "The path of the second uss file you want to compare." + USSFILEPATH1: "The path of the first USS file you want to compare.", + USSFILEPATH2: "The path of the second USS file you want to compare." }, EXAMPLES: { - EX1: `Compare the contents of the uss file "/u/user/test.txt" and "/u/user/test.txt"`, - EX2: `Compare the contents of the uss file "/u/user/test.txt" and "/u/user/test.txt" without sequence numbers` + EX1: `Compare the contents of the USS file "/u/user/test.txt" and "/u/user/test.txt"`, + EX2: `Compare the contents of the USS file "/u/user/test.txt" and "/u/user/test.txt" without sequence numbers` } }, LOCAL_FILE_USS_FILE: { - SUMMARY: "Compare content of a local file and a z/os uss file", - DESCRIPTION: "Compare content of a local file and a z/os uss file on your terminal (stdout).", + SUMMARY: "Compare the contents of a local file and a z/OS USS file", + DESCRIPTION: "Compare the contents of a local file and a z/OS USS file in your terminal (stdout).", POSITIONALS: { - LOCALFILEPATH: "The path of the local file you want to compare.", - USSFILEPATH: "The path of the uss file set you want to compare." + LOCALFILEPATH: "The path of the local file you want to compare.", + USSFILEPATH: "The path of the USS file set you want to compare." }, EXAMPLES: { - EX1: `Compare the contents of the local file and the uss file "./a.txt" and "/u/user/test.txt"`, - EX2: `Compare the contents of the local file and the uss file "./a.txt" and "/u/user/test.txt"` + + EX1: `Compare the contents of the local file and the USS file "./a.txt" and "/u/user/test.txt"`, + EX2: `Compare the contents of the local file and the USS file "./a.txt" and "/u/user/test.txt" ` + `without sequence numbers` } }, SPOOL_DD: { - SUMMARY: "Compare content of two spool dds", - DESCRIPTION: "Compare content of two spool dds on your terminal (stdout).", + SUMMARY: "Compare the contents of two spool dds", + DESCRIPTION: "Compare the contents of two spool dds in your terminal (stdout).", POSITIONALS: { - SPOOLDDDESCRIPTION1: "The name of the first job with the id of spool dd", - SPOOLDDDESCRIPTION2: "The name of the second job with the id of spool dd" + SPOOLDDDESCRIPTION1: "The name of the first job with the id of spool dd.", + SPOOLDDDESCRIPTION2: "The name of the second job with the id of spool dd." }, EXAMPLES: { EX1: `Compare the contents of the two spool dds "jobName1:jobId1:spoolId1" "jobName2:jobId2:spoolId2"`, - EX2: `Compare the contents of the two spool dds "jobName1:jobId1:spoolId1" "jobName2:jobId2:spoolId2"` + + EX2: `Compare the contents of the two spool dds "jobName1:jobId1:spoolId1" "jobName2:jobId2:spoolId2" ` + `without sequence numbers` } }, LOCAL_FILE_SPOOL_DD: { - SUMMARY: "Compare content of a local file and a spool dd", - DESCRIPTION: "Compare content of a local-file and a spool-dd on your terminal (stdout).", + SUMMARY: "Compare the contents of a local file and a spool dd", + DESCRIPTION: "Compare the contents of a local file and a spool dd in your terminal (stdout).", POSITIONALS: { - LOCALFILEPATH: "The path of the local file you want to compare.", - SPOOLDDDESCRIPTION: "The name of the job with the id of spool dd" + LOCALFILEPATH: "The path of the local file you want to compare.", + SPOOLDDDESCRIPTION: "The name of the job with the id of spool dd." }, EXAMPLES: { EX1: `Compare the contents of a local-file and a spool dd "./a.txt" "jobName:jobId:spoolId"`, - EX2: `Compare the contents of a local-file and a spool dd "./a.txt" "jobName:jobId:spoolId"` + + EX2: `Compare the contents of a local-file and a spool dd "./a.txt" "jobName:jobId:spoolId" ` + `without sequence numbers` } }, }, OPTIONS: { BINARY: "Transfer the content of the first data set in binary mode (no EBCDIC to ASCII conversion). If binary mode is set " + - "and the binary2 flag is not set then both datasets are transferred in binary mode.", + "and the binary2 flag is not set then both data sets are transferred in binary mode.", BINARY2: "Transfer the content of the second data set in binary mode.", ENCODING: "Transfer the content of the first data set with encoding mode, which means that data conversion is performed " + "using the file encoding specified. If encoding mode is set and the encoding2 flag is not set both data sets are " + @@ -897,13 +971,15 @@ export default { "lines display. If you want to limit the amount of data returned to only lines with differences use the context " + "lines option to reduce the matching lines to only those before and after non-matching lines. Using the value " + "of 0 strips all matching lines.", - BROWSERVIEW: "Opens the diffs between two given files in browser" + BROWSERVIEW: "Opens the diffs between two given files in browser." } }, HMIGRATE: { + SUMMARY: "Migrate data sets", DESCRIPTION: "Migrate data sets.", ACTIONS: { DATA_SET: { + SUMMARY: "Migrate a data set", DESCRIPTION: "Migrate a data set.", POSITIONALS: { DATASETNAME: "The name of the data set you want to migrate." @@ -918,9 +994,11 @@ export default { } }, HRECALL: { + SUMMARY: "Recall migrated data sets", DESCRIPTION: "Recall migrated data sets.", ACTIONS: { DATA_SET: { + SUMMARY: "Recall a migrated data set", DESCRIPTION: "Recall a migrated data set.", POSITIONALS: { DATASETNAME: "The name of the data set you want to recall." @@ -935,9 +1013,11 @@ export default { } }, RENAME: { + SUMMARY: "Rename a data set or member", DESCRIPTION: "Rename a data set or member.", ACTIONS: { DATA_SET: { + SUMMARY: "Rename a data set", DESCRIPTION: "Rename a data set.", POSITIONALS: { BEFOREDSNAME: "The name of the data set that you want to rename.", @@ -950,6 +1030,7 @@ export default { } }, DATA_SET_MEMBER: { + SUMMARY: "Rename a data set member", DESCRIPTION: "Rename a data set member.", POSITIONALS: { DSNAME: "The name of the data set the member belongs to.", diff --git a/packages/cli/src/zosfiles/ZosFiles.definition.ts b/packages/cli/src/zosfiles/ZosFiles.definition.ts index ec25ef6212..8317b63c42 100644 --- a/packages/cli/src/zosfiles/ZosFiles.definition.ts +++ b/packages/cli/src/zosfiles/ZosFiles.definition.ts @@ -27,6 +27,7 @@ import { UnmountDefinition } from "./unmount/Unmount.definition"; import { UploadDefinition } from "./upload/Upload.definition"; import { ViewDefinition } from "./view/View.definition"; import { ZosFilesOptionDefinitions } from "./ZosFiles.options"; +import { SearchDefinition } from "./search/Search.definition"; /** * This object defines the top level command group for zosfiles. This is not @@ -53,6 +54,7 @@ const definition: ICommandDefinition = { ListDefinition, MountDefinition, RenameDefinition, + SearchDefinition, UnmountDefinition, UploadDefinition, ViewDefinition diff --git a/packages/cli/src/zosfiles/ZosFiles.utils.ts b/packages/cli/src/zosfiles/ZosFiles.utils.ts deleted file mode 100644 index a61f9b8508..0000000000 --- a/packages/cli/src/zosfiles/ZosFiles.utils.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -// We are using arguments as an expected input to the function. Thus there is no generated code -// so we can ignore this linting error. -import { IDataSet, ZosFilesUtils } from "@zowe/zos-files-for-zowe-sdk"; - -/** - * @deprecated - use @zowe/zos-files-for-zowe-sdk's ZosFilesUtils.getDataSetFromName instead - * Converts the name of a data set to an IDataSet - * @param {string} name - the name in the form USER.DATA.SET | USER.DATA.SET(mem1) - */ -export function getDataSet(name: string): IDataSet { - return ZosFilesUtils.getDataSetFromName(name); -} diff --git a/packages/cli/src/zosfiles/ZosFilesBase.handler.ts b/packages/cli/src/zosfiles/ZosFilesBase.handler.ts index 6a35572af3..5ccca6bd67 100644 --- a/packages/cli/src/zosfiles/ZosFilesBase.handler.ts +++ b/packages/cli/src/zosfiles/ZosFilesBase.handler.ts @@ -13,7 +13,6 @@ import { AbstractSession, ICommandHandler, IHandlerParameters, - IProfile, ImperativeError, ConnectionPropsForSessCfg, ISession, @@ -76,17 +75,11 @@ export abstract class ZosFilesBaseHandler implements ICommandHandler { * * @param {IHandlerParameters} commandParameters Command parameters sent to the handler. * @param {AbstractSession} session The session object generated from the zosmf profile. - * @param {IProfile} zosmfProfile The zosmf profile that was loaded for the command. - * Never use this deprecated zosmfProfile parameter. - * It should have been removed for the V2 version of Zowe, but we missed it. - * There is no good reason to use it. Better techniques exist, and are - * implemented in all of the implementations of this abstract class. * * @returns {Promise} The response from the underlying zos-files api call. */ public abstract processWithSession( commandParameters: IHandlerParameters, session: AbstractSession, - zosmfProfile?: IProfile ): Promise; } diff --git a/packages/cli/src/zosfiles/copy/Copy.definition.ts b/packages/cli/src/zosfiles/copy/Copy.definition.ts index 7e385bf8fc..02268576df 100644 --- a/packages/cli/src/zosfiles/copy/Copy.definition.ts +++ b/packages/cli/src/zosfiles/copy/Copy.definition.ts @@ -27,6 +27,7 @@ export const CopyDefinition: ICommandDefinition = { name: "copy", aliases: ["cp"], type: "group", + summary: strings.SUMMARY, description: strings.DESCRIPTION, children: [ DsDefinition, diff --git a/packages/cli/src/zosfiles/copy/ds/Ds.definition.ts b/packages/cli/src/zosfiles/copy/ds/Ds.definition.ts index b3da933f0f..6324f99352 100644 --- a/packages/cli/src/zosfiles/copy/ds/Ds.definition.ts +++ b/packages/cli/src/zosfiles/copy/ds/Ds.definition.ts @@ -26,6 +26,7 @@ const strings = (require("../../-strings-/en").default as typeof i18nTypings).CO export const DsDefinition: ICommandDefinition = { name: "data-set", aliases: ["ds"], + summary: strings.SUMMARY, description: strings.DESCRIPTION, type: "command", handler: join(__dirname, "Ds.handler"), diff --git a/packages/cli/src/zosfiles/copy/dsclp/Dsclp.definition.ts b/packages/cli/src/zosfiles/copy/dsclp/Dsclp.definition.ts index 6fe542af64..2c3adc3f29 100644 --- a/packages/cli/src/zosfiles/copy/dsclp/Dsclp.definition.ts +++ b/packages/cli/src/zosfiles/copy/dsclp/Dsclp.definition.ts @@ -132,6 +132,7 @@ function buildChainedHandlerArgMapping(optionDefs: (ICommandOptionDefinition | I export const DsclpDefinition: ICommandDefinition = { name: "data-set-cross-lpar", aliases: ["dsclp"], + summary: strings.SUMMARY, description: strings.DESCRIPTION, type: "command", chainedHandlers: [ diff --git a/packages/cli/src/zosfiles/copy/dsclp/Dsclp.handler.ts b/packages/cli/src/zosfiles/copy/dsclp/Dsclp.handler.ts index f8873e1234..cd486f2315 100644 --- a/packages/cli/src/zosfiles/copy/dsclp/Dsclp.handler.ts +++ b/packages/cli/src/zosfiles/copy/dsclp/Dsclp.handler.ts @@ -58,7 +58,7 @@ export default class DsclpHandler extends ZosFilesBaseHandler { return async (targetDSN: string) => { const answer: string = await console.prompt( `The dataset '${targetDSN}' already exists on the target system. Do you want to overwrite it? [y/N]: `); - return (answer != null && (answer.toLowerCase() === "y" || answer.toLowerCase() === "yes")); + return answer != null && (answer.toLowerCase() === "y" || answer.toLowerCase() === "yes"); }; } } diff --git a/packages/cli/src/zosfiles/copy/dsclp/TargetProfile.handler.ts b/packages/cli/src/zosfiles/copy/dsclp/TargetProfile.handler.ts index 601122e863..16d046e0f0 100644 --- a/packages/cli/src/zosfiles/copy/dsclp/TargetProfile.handler.ts +++ b/packages/cli/src/zosfiles/copy/dsclp/TargetProfile.handler.ts @@ -28,12 +28,7 @@ export default class TargetProfileHandler extends ZosFilesBaseHandler { try { if (targetProfileName != null) { - if (ImperativeConfig.instance.config?.exists) { - targetCmdArgs = ImperativeConfig.instance.config.api.profiles.get(targetProfileName); - } else { - // eslint-disable-next-line deprecation/deprecation - targetCmdArgs = params.profiles.get("zosmf", false, targetProfileName); - } + targetCmdArgs = ImperativeConfig.instance.config.api.profiles.get(targetProfileName); } const targetPrefix = "target"; diff --git a/packages/cli/src/zosfiles/create/Create.definition.ts b/packages/cli/src/zosfiles/create/Create.definition.ts index c703cffde8..b15b164ad0 100644 --- a/packages/cli/src/zosfiles/create/Create.definition.ts +++ b/packages/cli/src/zosfiles/create/Create.definition.ts @@ -34,6 +34,7 @@ export const CreateDefinition: ICommandDefinition = { name: "create", aliases: ["cre"], type: "group", + summary: strings.SUMMARY, description: strings.DESCRIPTION, children: [PsDefinition, PdsDefinition, diff --git a/packages/cli/src/zosfiles/create/Create.options.ts b/packages/cli/src/zosfiles/create/Create.options.ts index 66abe8cde3..af11220f5a 100644 --- a/packages/cli/src/zosfiles/create/Create.options.ts +++ b/packages/cli/src/zosfiles/create/Create.options.ts @@ -31,20 +31,6 @@ export const ZosFilesCreateExtraOptions: { [key: string]: ICommandOptionDefiniti type: "boolean" }, - /** - * The indicator that we should print all allocation attributes - * @type {ICommandOptionDefinition} - * @deprecated - */ - // eslint-disable-next-line deprecation/deprecation - showAttributes: { - name: "show-attributes", - aliases: ["pa"], - description: strings.SHOWATTRIBUTES, - hidden: true, - type: "boolean" - }, - /** * The indicator that we should print all allocation attributes * @type {ICommandOptionDefinition} diff --git a/packages/cli/src/zosfiles/create/Create.utils.ts b/packages/cli/src/zosfiles/create/Create.utils.ts index 2a0d27a304..db69fd782a 100644 --- a/packages/cli/src/zosfiles/create/Create.utils.ts +++ b/packages/cli/src/zosfiles/create/Create.utils.ts @@ -33,7 +33,7 @@ export function generateZosmfOptions(commandArguments: Arguments): ICreateDataSe mgntclass: commandArguments.managementClass, dataclass: commandArguments.dataClass, dsntype: commandArguments.dataSetType, - showAttributes: commandArguments.showAttributes || commandArguments.attributes, + showAttributes: commandArguments.attributes, size: commandArguments.size, responseTimeout: commandArguments.responseTimeout })); diff --git a/packages/cli/src/zosfiles/create/binaryPds/BinaryPDS.definition.ts b/packages/cli/src/zosfiles/create/binaryPds/BinaryPDS.definition.ts index 03bf61c48b..c51f2c213f 100644 --- a/packages/cli/src/zosfiles/create/binaryPds/BinaryPDS.definition.ts +++ b/packages/cli/src/zosfiles/create/binaryPds/BinaryPDS.definition.ts @@ -24,6 +24,7 @@ const strings = (require("../../-strings-/en").default as typeof i18nTypings).CR export const BinaryPDSDefinition: ICommandDefinition = { name: "data-set-binary", aliases: ["bin"], + summary: strings.ACTIONS.DATA_SET_BINARY.SUMMARY, description: strings.ACTIONS.DATA_SET_BINARY.DESCRIPTION, type: "command", handler: __dirname + "/BinaryPDS.handler", @@ -52,7 +53,6 @@ export const BinaryPDSDefinition: ICommandDefinition = { ZosFilesCreateOptions.dataclass, ZosFilesCreateOptions.unit, ZosFilesCreateOptions.dsntype, - ZosFilesCreateExtraOptions.showAttributes, ZosFilesCreateExtraOptions.attributes ].sort((a, b) => a.name.localeCompare(b.name)), examples: [ diff --git a/packages/cli/src/zosfiles/create/cPds/CPDS.definition.ts b/packages/cli/src/zosfiles/create/cPds/CPDS.definition.ts index a6c00f95e1..bfd98cbc14 100644 --- a/packages/cli/src/zosfiles/create/cPds/CPDS.definition.ts +++ b/packages/cli/src/zosfiles/create/cPds/CPDS.definition.ts @@ -24,6 +24,7 @@ const strings = (require("../../-strings-/en").default as typeof i18nTypings).CR export const CPDSDefinition: ICommandDefinition = { name: "data-set-c", aliases: ["dsc"], + summary: strings.ACTIONS.DATA_SET_C.SUMMARY, description: strings.ACTIONS.DATA_SET_C.DESCRIPTION, type: "command", handler: __dirname + "/CPDS.handler", @@ -52,7 +53,6 @@ export const CPDSDefinition: ICommandDefinition = { ZosFilesCreateOptions.dataclass, ZosFilesCreateOptions.unit, ZosFilesCreateOptions.dsntype, - ZosFilesCreateExtraOptions.showAttributes, ZosFilesCreateExtraOptions.attributes ].sort((a, b) => a.name.localeCompare(b.name)), examples: [ diff --git a/packages/cli/src/zosfiles/create/classicPds/ClassicPDS.definition.ts b/packages/cli/src/zosfiles/create/classicPds/ClassicPDS.definition.ts index e04af04c99..b2d10ea79e 100644 --- a/packages/cli/src/zosfiles/create/classicPds/ClassicPDS.definition.ts +++ b/packages/cli/src/zosfiles/create/classicPds/ClassicPDS.definition.ts @@ -24,6 +24,7 @@ const strings = (require("../../-strings-/en").default as typeof i18nTypings).CR export const ClassicPDSDefinition: ICommandDefinition = { name: "data-set-classic", aliases: ["classic"], + summary: strings.ACTIONS.DATA_SET_CLASSIC.SUMMARY, description: strings.ACTIONS.DATA_SET_CLASSIC.DESCRIPTION, type: "command", handler: __dirname + "/ClassicPDS.handler", @@ -52,7 +53,6 @@ export const ClassicPDSDefinition: ICommandDefinition = { ZosFilesCreateOptions.dataclass, ZosFilesCreateOptions.unit, ZosFilesCreateOptions.dsntype, - ZosFilesCreateExtraOptions.showAttributes, ZosFilesCreateExtraOptions.attributes ].sort((a, b) => a.name.localeCompare(b.name)), examples: [ diff --git a/packages/cli/src/zosfiles/create/ds/ds.definition.ts b/packages/cli/src/zosfiles/create/ds/ds.definition.ts index 561b66452c..4703ad758e 100644 --- a/packages/cli/src/zosfiles/create/ds/ds.definition.ts +++ b/packages/cli/src/zosfiles/create/ds/ds.definition.ts @@ -23,6 +23,7 @@ const strings = (require("../../-strings-/en").default as typeof i18nTypings).CR export const DsDefinition: ICommandDefinition = { name: "data-set", aliases: ["ds"], + summary: strings.ACTIONS.DATA_SET_LIKE.SUMMARY, description: strings.ACTIONS.DATA_SET_LIKE.DESCRIPTION, type: "command", handler: __dirname + "/ds.handler", @@ -51,7 +52,6 @@ export const DsDefinition: ICommandDefinition = { ZosFilesCreateOptions.dataclass, ZosFilesCreateOptions.unit, ZosFilesCreateOptions.dsntype, - ZosFilesCreateExtraOptions.showAttributes, ZosFilesCreateExtraOptions.attributes, ZosFilesCreateExtraOptions.like ].sort((a, b) => a.name.localeCompare(b.name)), diff --git a/packages/cli/src/zosfiles/create/pds/Pds.definition.ts b/packages/cli/src/zosfiles/create/pds/Pds.definition.ts index 7dd72ab8d5..0986268552 100644 --- a/packages/cli/src/zosfiles/create/pds/Pds.definition.ts +++ b/packages/cli/src/zosfiles/create/pds/Pds.definition.ts @@ -24,6 +24,7 @@ const strings = (require("../../-strings-/en").default as typeof i18nTypings).CR export const PdsDefinition: ICommandDefinition = { name: "data-set-partitioned", aliases: ["pds"], + summary: strings.ACTIONS.DATA_SET_PARTITIONED.SUMMARY, description: strings.ACTIONS.DATA_SET_PARTITIONED.DESCRIPTION, type: "command", handler: __dirname + "/Pds.handler", @@ -53,7 +54,6 @@ export const PdsDefinition: ICommandDefinition = { ZosFilesCreateOptions.dataclass, ZosFilesCreateOptions.unit, ZosFilesCreateOptions.dsntype, - ZosFilesCreateExtraOptions.showAttributes, ZosFilesCreateExtraOptions.attributes ].sort((a, b) => a.name.localeCompare(b.name)), examples: [ diff --git a/packages/cli/src/zosfiles/create/ps/Ps.definition.ts b/packages/cli/src/zosfiles/create/ps/Ps.definition.ts index 9d3a46bceb..40ebc5f558 100644 --- a/packages/cli/src/zosfiles/create/ps/Ps.definition.ts +++ b/packages/cli/src/zosfiles/create/ps/Ps.definition.ts @@ -25,6 +25,7 @@ const strings = (require("../../-strings-/en").default as typeof i18nTypings).CR export const PsDefinition: ICommandDefinition = { name: "data-set-sequential", aliases: ["ps"], + summary: strings.ACTIONS.DATA_SET_SEQUENTIAL.SUMMARY, description: strings.ACTIONS.DATA_SET_SEQUENTIAL.DESCRIPTION, type: "command", handler: __dirname + "/Ps.handler", @@ -52,7 +53,6 @@ export const PsDefinition: ICommandDefinition = { ZosFilesCreateOptions.mgntclass, ZosFilesCreateOptions.dataclass, ZosFilesCreateOptions.unit, - ZosFilesCreateExtraOptions.showAttributes, ZosFilesCreateExtraOptions.attributes ].sort((a, b) => a.name.localeCompare(b.name)), examples: [ diff --git a/packages/cli/src/zosfiles/create/vsam/vsam.definition.ts b/packages/cli/src/zosfiles/create/vsam/vsam.definition.ts index a79140b499..479ab00774 100644 --- a/packages/cli/src/zosfiles/create/vsam/vsam.definition.ts +++ b/packages/cli/src/zosfiles/create/vsam/vsam.definition.ts @@ -46,6 +46,7 @@ const vsamRetainFor = Object.assign({}, ...[VsamCreateOptions.retainFor]); export const VsamDefinition: ICommandDefinition = { name: "data-set-vsam", aliases: ["vsam"], + summary: vsamStrings.SUMMARY, description: vsamStrings.DESCRIPTION, type: "command", handler: __dirname + "/vsam.handler", @@ -70,7 +71,6 @@ export const VsamDefinition: ICommandDefinition = { ZosFilesCreateOptions.dataclass, vsamRetainFor, VsamCreateOptions.retainTo, - ZosFilesCreateExtraOptions.showAttributes, ZosFilesCreateExtraOptions.attributes ].sort((a, b) => a.name.localeCompare(b.name)), examples: [ diff --git a/packages/cli/src/zosfiles/create/vsam/vsam.handler.ts b/packages/cli/src/zosfiles/create/vsam/vsam.handler.ts index bb2bea58ec..7db4731af5 100644 --- a/packages/cli/src/zosfiles/create/vsam/vsam.handler.ts +++ b/packages/cli/src/zosfiles/create/vsam/vsam.handler.ts @@ -30,7 +30,7 @@ export default class VsamHandler extends ZosFilesBaseHandler { dataclass: commandParameters.arguments.dataClass, retainFor: commandParameters.arguments.retainFor, retainTo: commandParameters.arguments.retainTo, - showAttributes: commandParameters.arguments.showAttributes || commandParameters.arguments.attributes, + showAttributes: commandParameters.arguments.attributes, responseTimeout: commandParameters.arguments.responseTimeout })); diff --git a/packages/cli/src/zosfiles/delete/Delete.definition.ts b/packages/cli/src/zosfiles/delete/Delete.definition.ts index 654c9337ad..d609aa0ae4 100644 --- a/packages/cli/src/zosfiles/delete/Delete.definition.ts +++ b/packages/cli/src/zosfiles/delete/Delete.definition.ts @@ -30,6 +30,7 @@ export const DeleteDefinition: ICommandDefinition = { name: "delete", aliases: ["del"], type: "group", + summary: strings.SUMMARY, description: strings.DESCRIPTION, children: [ DsDefinition, diff --git a/packages/cli/src/zosfiles/delete/ds/Ds.definition.ts b/packages/cli/src/zosfiles/delete/ds/Ds.definition.ts index 924d670dd5..3d320054d6 100644 --- a/packages/cli/src/zosfiles/delete/ds/Ds.definition.ts +++ b/packages/cli/src/zosfiles/delete/ds/Ds.definition.ts @@ -25,6 +25,7 @@ const strings = (require("../../-strings-/en").default as typeof i18nTypings).DE export const DsDefinition: ICommandDefinition = { name: "data-set", aliases: ["ds"], + summary: strings.SUMMARY, description: strings.DESCRIPTION, type: "command", handler: join(__dirname, "Ds.handler"), diff --git a/packages/cli/src/zosfiles/delete/mds/Mds.definition.ts b/packages/cli/src/zosfiles/delete/mds/Mds.definition.ts index a6c2249bbd..745889cfda 100644 --- a/packages/cli/src/zosfiles/delete/mds/Mds.definition.ts +++ b/packages/cli/src/zosfiles/delete/mds/Mds.definition.ts @@ -19,6 +19,7 @@ const strings = (require("../../-strings-/en").default as typeof i18nTypings).DE export const MdsDefinition: ICommandDefinition = { name: "migrated-data-set", aliases: ["mds"], + summary: strings.SUMMARY, description: strings.DESCRIPTION, type: "command", handler: __dirname + "/Mds.handler", diff --git a/packages/cli/src/zosfiles/delete/uss/Uss.definition.ts b/packages/cli/src/zosfiles/delete/uss/Uss.definition.ts index d58a245e5b..2a8f09ca3b 100644 --- a/packages/cli/src/zosfiles/delete/uss/Uss.definition.ts +++ b/packages/cli/src/zosfiles/delete/uss/Uss.definition.ts @@ -25,6 +25,7 @@ const strings = (require("../../-strings-/en").default as typeof i18nTypings).DE export const UssDefinition: ICommandDefinition = { name: "uss-file", aliases: ["uf", "uss"], + summary: strings.SUMMARY, description: strings.DESCRIPTION, type: "command", handler: join(__dirname, "Uss.handler"), @@ -39,7 +40,7 @@ export const UssDefinition: ICommandDefinition = { required: true } ], - options: ([ + options: [ { name: "for-sure", aliases: ["f"], @@ -54,7 +55,7 @@ export const UssDefinition: ICommandDefinition = { type: "boolean", required: false } - ]), + ], examples: [ { description: strings.EXAMPLES.EX1, diff --git a/packages/cli/src/zosfiles/delete/vsam/Vsam.definition.ts b/packages/cli/src/zosfiles/delete/vsam/Vsam.definition.ts index 57216654ee..08893a34e0 100644 --- a/packages/cli/src/zosfiles/delete/vsam/Vsam.definition.ts +++ b/packages/cli/src/zosfiles/delete/vsam/Vsam.definition.ts @@ -25,6 +25,7 @@ const strings = (require("../../-strings-/en").default as typeof i18nTypings).DE export const VsamDefinition: ICommandDefinition = { name: "data-set-vsam", aliases: ["vsam"], + summary: strings.SUMMARY, description: strings.DESCRIPTION, type: "command", handler: join(__dirname, "Vsam.handler"), diff --git a/packages/cli/src/zosfiles/download/Download.options.ts b/packages/cli/src/zosfiles/download/Download.options.ts index 2220db8cb4..383250f378 100644 --- a/packages/cli/src/zosfiles/download/Download.options.ts +++ b/packages/cli/src/zosfiles/download/Download.options.ts @@ -16,7 +16,8 @@ import i18nTypings from "../-strings-/en"; // Does not use the import in anticipation of some internationalization work to be done later. const strings = (require("../-strings-/en").default as typeof i18nTypings).DOWNLOAD.OPTIONS; -const maxConcurrentRequestsMaxValue = 99999; +/** @internal */ +export const maxConcurrentRequestsMaxValue = 100; /** * Object containing all options to be used by the Download data set API diff --git a/packages/cli/src/zosfiles/edit/Edit.handler.ts b/packages/cli/src/zosfiles/edit/Edit.handler.ts index 065e74e11a..7c8a99d9d6 100644 --- a/packages/cli/src/zosfiles/edit/Edit.handler.ts +++ b/packages/cli/src/zosfiles/edit/Edit.handler.ts @@ -25,7 +25,7 @@ export default class EditHandler extends ZosFilesBaseHandler { let lfFile: ILocalFile = { tempPath: null, fileName: commandParameters.arguments.ussFilePath ?? commandParameters.arguments.dataSetName, - fileType: commandParameters.positionals[2].includes('d') ? "ds" : "uss", + fileType: commandParameters.positionals[2].toString().includes('d') ? "ds" : "uss", guiAvail: ProcessUtils.isGuiAvailable() === GuiResult.GUI_AVAILABLE, conflict: false, encoding: commandParameters.arguments.encoding, diff --git a/packages/cli/src/zosfiles/edit/Edit.options.ts b/packages/cli/src/zosfiles/edit/Edit.options.ts index 8289f9b12a..e866f29f6d 100644 --- a/packages/cli/src/zosfiles/edit/Edit.options.ts +++ b/packages/cli/src/zosfiles/edit/Edit.options.ts @@ -65,4 +65,4 @@ export const EditOptions: { [key: string]: ICommandOptionDefinition } = { type: "string", conflictsWith: ["binary"] }, -}; \ No newline at end of file +}; diff --git a/packages/cli/src/zosfiles/edit/Edit.utils.ts b/packages/cli/src/zosfiles/edit/Edit.utils.ts index 024315c6e1..86a7ec8d9f 100644 --- a/packages/cli/src/zosfiles/edit/Edit.utils.ts +++ b/packages/cli/src/zosfiles/edit/Edit.utils.ts @@ -72,9 +72,9 @@ export class EditUtilities { */ public static async buildTempPath(lfFile: ILocalFile, commandParameters: IHandlerParameters): Promise{ // find the appropriate extension for either uss or ds - const ussExt = (lfFile.fileType === 'uss' && lfFile.fileName.includes(".")) ? lfFile.fileName.split(".").pop() : ""; - let ext = "." + (lfFile.fileType === 'uss' ? ussExt : (commandParameters.arguments.extension ?? "txt")); - ext = (ext === "." ? "" : ext); + const ussExt = lfFile.fileType === 'uss' && lfFile.fileName.includes(".") ? lfFile.fileName.split(".").pop() : ""; + let ext = "." + (lfFile.fileType === 'uss' ? ussExt : commandParameters.arguments.extension ?? "txt"); + ext = ext === "." ? "" : ext; if (lfFile.fileType === 'uss'){ // Hash in a repeatable way if uss fileName (in case presence of special chars) const crypto = require("crypto"); @@ -114,7 +114,7 @@ export class EditUtilities { public static async promptUser(prompt: Prompt, conflict?: boolean): Promise{ let input; let promptText; - const promptPrefix = (conflict ? 'CONFLICT: ' : ''); + const promptPrefix = conflict ? 'CONFLICT: ' : ''; switch (prompt){ case Prompt.useStash: promptText = 'Keep and continue editing found temp file? y/n'; @@ -199,12 +199,12 @@ export class EditUtilities { name2: "remote file" }; - helper.browserView = (gui === GuiResult.GUI_AVAILABLE); + helper.browserView = gui === GuiResult.GUI_AVAILABLE; const lf: Buffer = await handlerDs.getFile1(session, commandParameters.arguments, helper); let mf: string | Buffer; try{ - if (commandParameters.positionals[2].includes('d')){ + if (commandParameters.positionals[2].toString().includes('d')){ mf = await handlerDs.getFile2(session, commandParameters.arguments, helper); }else{ mf = await handlerUss.getFile2(session, commandParameters.arguments, helper); diff --git a/packages/cli/src/zosfiles/hMigrate/HMigrate.definition.ts b/packages/cli/src/zosfiles/hMigrate/HMigrate.definition.ts index dfd0c01ea4..6a78581cb5 100644 --- a/packages/cli/src/zosfiles/hMigrate/HMigrate.definition.ts +++ b/packages/cli/src/zosfiles/hMigrate/HMigrate.definition.ts @@ -15,7 +15,7 @@ import { DsDefinition } from "./ds/Ds.definition"; import i18nTypings from "../-strings-/en"; // Does not use the import in anticipation of some internationalization work to be done later. -const { DESCRIPTION } = (require("../-strings-/en").default as typeof i18nTypings).HMIGRATE; +const { DESCRIPTION, SUMMARY } = (require("../-strings-/en").default as typeof i18nTypings).HMIGRATE; /** * hMigrate group definition containing its description and children @@ -25,6 +25,7 @@ export const HMigrateDefinition: ICommandDefinition = { name: "migrate", aliases: ["hmigr", "hMigrate"], type: "group", + summary: SUMMARY, description: DESCRIPTION, children: [ DsDefinition diff --git a/packages/cli/src/zosfiles/hMigrate/ds/Ds.definition.ts b/packages/cli/src/zosfiles/hMigrate/ds/Ds.definition.ts index 96086790d5..8e5b30b2f7 100644 --- a/packages/cli/src/zosfiles/hMigrate/ds/Ds.definition.ts +++ b/packages/cli/src/zosfiles/hMigrate/ds/Ds.definition.ts @@ -20,6 +20,7 @@ const dSStrings = strings.HMIGRATE.ACTIONS.DATA_SET; export const DsDefinition: ICommandDefinition = { name: "data-set", aliases: ["ds"], + summary: dSStrings.SUMMARY, description: dSStrings.DESCRIPTION, type: "command", handler: __dirname + "/Ds.handler", diff --git a/packages/cli/src/zosfiles/hRecall/HRecall.definition.ts b/packages/cli/src/zosfiles/hRecall/HRecall.definition.ts index 0612562319..f06883e9ab 100644 --- a/packages/cli/src/zosfiles/hRecall/HRecall.definition.ts +++ b/packages/cli/src/zosfiles/hRecall/HRecall.definition.ts @@ -15,7 +15,7 @@ import { DsDefinition } from "./ds/Ds.definition"; import i18nTypings from "../-strings-/en"; // Does not use the import in anticipation of some internationalization work to be done later. -const { DESCRIPTION } = (require("../-strings-/en").default as typeof i18nTypings).HRECALL; +const { DESCRIPTION, SUMMARY } = (require("../-strings-/en").default as typeof i18nTypings).HRECALL; /** * hRecall group definition containing its description and children @@ -25,6 +25,7 @@ export const HRecallDefinition: ICommandDefinition = { name: "recall", aliases: ["hrec", "hRecall"], type: "group", + summary: SUMMARY, description: DESCRIPTION, children: [ DsDefinition diff --git a/packages/cli/src/zosfiles/hRecall/ds/Ds.definition.ts b/packages/cli/src/zosfiles/hRecall/ds/Ds.definition.ts index 5bbf518b0f..116319a85d 100644 --- a/packages/cli/src/zosfiles/hRecall/ds/Ds.definition.ts +++ b/packages/cli/src/zosfiles/hRecall/ds/Ds.definition.ts @@ -20,6 +20,7 @@ const dSStrings = strings.HRECALL.ACTIONS.DATA_SET; export const DsDefinition: ICommandDefinition = { name: "data-set", aliases: ["ds"], + summary: dSStrings.SUMMARY, description: dSStrings.DESCRIPTION, type: "command", handler: __dirname + "/Ds.handler", diff --git a/packages/cli/src/zosfiles/rename/Rename.definition.ts b/packages/cli/src/zosfiles/rename/Rename.definition.ts index c02e0592a8..7341371759 100644 --- a/packages/cli/src/zosfiles/rename/Rename.definition.ts +++ b/packages/cli/src/zosfiles/rename/Rename.definition.ts @@ -26,6 +26,7 @@ export const RenameDefinition: ICommandDefinition = { name: "rename", aliases: [], type: "group", + summary: strings.SUMMARY, description: strings.DESCRIPTION, children: [ DsDefinition, diff --git a/packages/cli/src/zosfiles/rename/ds/Ds.definition.ts b/packages/cli/src/zosfiles/rename/ds/Ds.definition.ts index e641535bf8..732cc653f7 100644 --- a/packages/cli/src/zosfiles/rename/ds/Ds.definition.ts +++ b/packages/cli/src/zosfiles/rename/ds/Ds.definition.ts @@ -20,6 +20,7 @@ const dsStrings = strings.RENAME.ACTIONS.DATA_SET; export const DsDefinition: ICommandDefinition = { name: "data-set", aliases: ["ds"], + summary: dsStrings.SUMMARY, description: dsStrings.DESCRIPTION, type: "command", handler: __dirname + "/Ds.handler", diff --git a/packages/cli/src/zosfiles/rename/dsm/Dsm.definition.ts b/packages/cli/src/zosfiles/rename/dsm/Dsm.definition.ts index 64f385c2b5..e475c63110 100644 --- a/packages/cli/src/zosfiles/rename/dsm/Dsm.definition.ts +++ b/packages/cli/src/zosfiles/rename/dsm/Dsm.definition.ts @@ -20,6 +20,7 @@ const dsmStrings = strings.RENAME.ACTIONS.DATA_SET_MEMBER; export const DsmDefinition: ICommandDefinition = { name: "data-set-member", aliases: ["dsm"], + summary: dsmStrings.SUMMARY, description: dsmStrings.DESCRIPTION, type: "command", handler: __dirname + "/Dsm.handler", diff --git a/packages/cli/src/zosfiles/search/Search.definition.ts b/packages/cli/src/zosfiles/search/Search.definition.ts new file mode 100644 index 0000000000..2ea11289db --- /dev/null +++ b/packages/cli/src/zosfiles/search/Search.definition.ts @@ -0,0 +1,32 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ICommandDefinition } from "@zowe/imperative"; +import { DataSetsDefinition } from "./ds/DataSets.definition"; + +import i18nTypings from "../-strings-/en"; + +// Does not use the import in anticipation of some internationalization work to be done later. +const strings = (require("../-strings-/en").default as typeof i18nTypings).SEARCH; + +/** + * Download group definition containing its description and children + * @type {ICommandDefinition} + */ +export const SearchDefinition: ICommandDefinition = { + name: "search", + type: "group", + summary: strings.SUMMARY, + description: strings.DESCRIPTION, + children: [ + DataSetsDefinition + ] +}; diff --git a/packages/cli/src/zosfiles/search/ds/DataSets.definition.ts b/packages/cli/src/zosfiles/search/ds/DataSets.definition.ts new file mode 100644 index 0000000000..735a02b4f9 --- /dev/null +++ b/packages/cli/src/zosfiles/search/ds/DataSets.definition.ts @@ -0,0 +1,96 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ICommandDefinition } from "@zowe/imperative"; +import i18nTypings from "../../-strings-/en"; +import { maxConcurrentRequestsMaxValue } from "../../download/Download.options"; + +// Does not use the import in anticipation of some internationalization work to be done later. +const strings = (require("../../-strings-/en").default as typeof i18nTypings).SEARCH; +const dataSetStrings = strings.ACTIONS.DS; + +/** + * List all data sets and members command definition containing its description, examples and/or options + * @type {ICommandDefinition} + */ +export const DataSetsDefinition: ICommandDefinition = { + name: "data-sets", + aliases: ["ds"], + summary: dataSetStrings.SUMMARY, + description: dataSetStrings.DESCRIPTION, + type: "command", + handler: __dirname + "/DataSets.handler", + profile: { + optional: ["zosmf"] + }, + positionals: [ + { + name: "pattern", + description: dataSetStrings.POSITIONALS.PATTERN, + type: "string", + required: true + }, + { + name: "searchString", + description: strings.OPTIONS.SEARCHSTRING, + type: "string", + required: true + } + ], + options: [ + { + name: "case-sensitive", + aliases: ["cs"], + description: dataSetStrings.OPTIONS.CASESENSITIVE, + type: "boolean", + defaultValue: false + }, + { + name: "mainframe-search", + aliases: ["ms"], + description: dataSetStrings.OPTIONS.MAINFRAMESEARCH, + type: "boolean", + defaultValue: false + }, + { + name: "max-concurrent-requests", + aliases: ["mcr"], + description: dataSetStrings.OPTIONS.MAX_CONCURRENT_REQUESTS, + type: "number", + defaultValue: 1, + numericValueRange: [1, maxConcurrentRequestsMaxValue] + }, + { + name: "timeout", + aliases: ["to"], + description: dataSetStrings.OPTIONS.TIMEOUT, + type: "number" + } + ], + examples: [ + { + description: dataSetStrings.EXAMPLES.EX1.DESCRIPTION, + options: dataSetStrings.EXAMPLES.EX1.OPTIONS + }, + { + description: dataSetStrings.EXAMPLES.EX2.DESCRIPTION, + options: dataSetStrings.EXAMPLES.EX2.OPTIONS + }, + { + description: dataSetStrings.EXAMPLES.EX3.DESCRIPTION, + options: dataSetStrings.EXAMPLES.EX3.OPTIONS + }, + { + description: dataSetStrings.EXAMPLES.EX4.DESCRIPTION, + options: dataSetStrings.EXAMPLES.EX4.OPTIONS + } + ] +}; diff --git a/packages/cli/src/zosfiles/search/ds/DataSets.handler.ts b/packages/cli/src/zosfiles/search/ds/DataSets.handler.ts new file mode 100644 index 0000000000..50f50d2dd1 --- /dev/null +++ b/packages/cli/src/zosfiles/search/ds/DataSets.handler.ts @@ -0,0 +1,44 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { AbstractSession, IHandlerParameters, ITaskWithStatus, TaskStage } from "@zowe/imperative"; +import { ISearchOptions, IZosFilesResponse, Search } from "@zowe/zos-files-for-zowe-sdk"; +import { ZosFilesBaseHandler } from "../../ZosFilesBase.handler"; + +/** + * Handler to list a data set members + * @export + */ +export default class DataSetsHandler extends ZosFilesBaseHandler { + public async processWithSession(commandParameters: IHandlerParameters, session: AbstractSession): Promise { + const task: ITaskWithStatus = { + percentComplete: 0, + statusMessage: "Starting search...", + stageName: TaskStage.NOT_STARTED + }; + + const searchOptions: ISearchOptions = { + pattern: commandParameters.arguments.pattern, + searchString: commandParameters.arguments.searchString, + timeout: commandParameters.arguments.timeout, + mainframeSearch: commandParameters.arguments.mainframeSearch, + maxConcurrentRequests: commandParameters.arguments.maxConcurrentRequests, + caseSensitive: commandParameters.arguments.caseSensitive, + progressTask: task + }; + + commandParameters.response.progress.startBar({task}); + const response = await Search.dataSets(session, searchOptions); + commandParameters.response.progress.endBar(); + + return response; + } +} diff --git a/packages/cli/src/zosfiles/upload/Upload.definition.ts b/packages/cli/src/zosfiles/upload/Upload.definition.ts index 7f75ab4c19..e35c8cf2ed 100644 --- a/packages/cli/src/zosfiles/upload/Upload.definition.ts +++ b/packages/cli/src/zosfiles/upload/Upload.definition.ts @@ -28,6 +28,7 @@ export const UploadDefinition: ICommandDefinition = { name: "upload", aliases: ["ul"], type: "group", + summary: strings.SUMMARY, description: strings.DESCRIPTION, children: [ FileToDataSetDefinition, diff --git a/packages/cli/src/zosfiles/upload/Upload.options.ts b/packages/cli/src/zosfiles/upload/Upload.options.ts index 69b6248dfb..fe1615ce0d 100644 --- a/packages/cli/src/zosfiles/upload/Upload.options.ts +++ b/packages/cli/src/zosfiles/upload/Upload.options.ts @@ -10,14 +10,13 @@ */ import { ICommandOptionDefinition } from "@zowe/imperative"; +import { maxConcurrentRequestsMaxValue } from "../download/Download.options"; import i18nTypings from "../-strings-/en"; // Does not use the import in anticipation of some internationalization work to be done later. const strings = (require("../-strings-/en").default as typeof i18nTypings).UPLOAD.OPTIONS; -const maxConcurrentRequestsMaxValue = 99999; - /** * Object containing all options to be used by the Upload API */ diff --git a/packages/cli/src/zosfiles/upload/dtp/DirToPds.definition.ts b/packages/cli/src/zosfiles/upload/dtp/DirToPds.definition.ts index 62b7274fe6..3b5e40ae99 100644 --- a/packages/cli/src/zosfiles/upload/dtp/DirToPds.definition.ts +++ b/packages/cli/src/zosfiles/upload/dtp/DirToPds.definition.ts @@ -24,6 +24,7 @@ const strings = (require("../../-strings-/en").default as typeof i18nTypings).UP export const DirToPdsDefinition: ICommandDefinition = { name: "dir-to-pds", aliases: ["dtp"], + summary: strings.SUMMARY, description: strings.DESCRIPTION, type: "command", handler: path.join(__dirname, "/DirToPds.handler"), diff --git a/packages/cli/src/zosfiles/upload/ftds/FileToDataSet.definition.ts b/packages/cli/src/zosfiles/upload/ftds/FileToDataSet.definition.ts index efb848f84c..edae2b7653 100644 --- a/packages/cli/src/zosfiles/upload/ftds/FileToDataSet.definition.ts +++ b/packages/cli/src/zosfiles/upload/ftds/FileToDataSet.definition.ts @@ -24,6 +24,7 @@ const strings = (require("../../-strings-/en").default as typeof i18nTypings).UP export const FileToDataSetDefinition: ICommandDefinition = { name: "file-to-data-set", aliases: ["ftds"], + summary: strings.SUMMARY, description: strings.DESCRIPTION, type: "command", handler: path.join(__dirname, "/FileToDataSet.handler"), diff --git a/packages/cli/src/zosfiles/upload/ftu/FileToUSS.definition.ts b/packages/cli/src/zosfiles/upload/ftu/FileToUSS.definition.ts index 7de3726218..1cd07d4b82 100644 --- a/packages/cli/src/zosfiles/upload/ftu/FileToUSS.definition.ts +++ b/packages/cli/src/zosfiles/upload/ftu/FileToUSS.definition.ts @@ -25,6 +25,7 @@ const strings = (require("../../-strings-/en").default as typeof i18nTypings).UP export const FileToUSSDefinition: ICommandDefinition = { name: "file-to-uss", aliases: ["ftu"], + summary: strings.SUMMARY, description: strings.DESCRIPTION, type: "command", handler: path.join(__dirname, "/FileToUSS.handler"), diff --git a/packages/cli/src/zosfiles/upload/stds/StdinToDataSet.definition.ts b/packages/cli/src/zosfiles/upload/stds/StdinToDataSet.definition.ts index 3953d2a670..5e31e016ae 100644 --- a/packages/cli/src/zosfiles/upload/stds/StdinToDataSet.definition.ts +++ b/packages/cli/src/zosfiles/upload/stds/StdinToDataSet.definition.ts @@ -24,6 +24,7 @@ const strings = (require("../../-strings-/en").default as typeof i18nTypings).UP export const StdinToDataSetDefinition: ICommandDefinition = { name: "stdin-to-data-set", aliases: ["stds"], + summary: strings.SUMMARY, description: strings.DESCRIPTION, type: "command", handler: path.join(__dirname, "/StdinToDataSet.handler"), diff --git a/packages/cli/src/zosjobs/-strings-/en.ts b/packages/cli/src/zosjobs/-strings-/en.ts index 1c36db2abb..fb170495db 100644 --- a/packages/cli/src/zosjobs/-strings-/en.ts +++ b/packages/cli/src/zosjobs/-strings-/en.ts @@ -18,7 +18,7 @@ export default { ACTIONS: { JOB: { SUMMARY: "Cancel a single job by job ID", - DESCRIPTION: "Cancel a single job by job ID", + DESCRIPTION: "Cancel a single job by job ID.", POSITIONALS: { JOB_ID: "The job ID (e.g. JOB00123) of the job. Job ID is a unique identifier for z/OS batch jobs " + "-- no two jobs on one system can have the same ID. Note: z/OS allows you to abbreviate " + @@ -73,13 +73,50 @@ export default { } } }, + SEARCH: { + SUMMARY: "Search the spool output of a z/OS job", + DESCRIPTION: "Search the spool output of a job.", + ACTIONS: { + JOB: { + SUMMARY: "Search the spool output of a job.", + DESCRIPTION: "Search the spool output of a job.", + POSITIONALS: { + JOBNAME: "The job name to search. Wildcards are accepted for the job name." + + " You can use, for example \"USERJOB*\" to search all jobs that start" + + " with USERJOB." + }, + OPTIONS: { + SEARCHSTRING: "The string to search for in the spool output.", + SEARCHREGEX: "The regular expression to search for in the spool output.", + CASEINSENSITIVE: "The search is case insensitive or not.", + SEARCHLIMIT: "The maximum number of matching lines to return for an individual spool file.", + FILELIMIT: "The maximum number of spool files to search." + }, + EXAMPLES: { + EX1: { + DESCRIPTION: "Search all jobs named USERJOB for the string \"RC=0000\"", + OPTIONS: "\"USERJOB\" --search-string \"RC=0000\"", + }, + EX2: { + DESCRIPTION: "Search all jobs that start with USER for the string \"ENDED\"", + OPTIONS: "\"USER*\" --search-string \"ENDED\"", + }, + EX3: { + DESCRIPTION: "Search all jobs named USERJOB for the string \"COND CODE\", with the options" + + " case sensitive and a search limit of 5", + OPTIONS: "\"USERJOB\" --search-string \"COND CODE\" --case-insensitive false --search-limit 5" + }, + } + } + } + }, DELETE: { SUMMARY: "Delete a z/OS job or jobs", DESCRIPTION: "Delete a single job by job ID or delete multiple jobs in OUTPUT status.", ACTIONS: { JOB: { SUMMARY: "Delete a single job by job ID", - DESCRIPTION: "Delete a single job by job ID", + DESCRIPTION: "Delete a single job by job ID.", POSITIONALS: { JOB_ID: "The job ID (e.g. JOB00123) of the job. Job ID is a unique identifier for z/OS batch jobs " + "-- no two jobs on one system can have the same ID. Note: z/OS allows you to abbreviate " + @@ -123,7 +160,7 @@ export default { LIST: { }, OPTIONS: { - MODIFY_VERSION: "Using this option to set X-IBM-Job-Modify-Version to \"1.0\" will make the delete job API aynchronous. " + + MODIFY_VERSION: "Using this option to set X-IBM-Job-Modify-Version to \"1.0\" will make the delete job API asynchronous. " + "Otherwise, it will be synchronous by default." }, SUBMIT: { diff --git a/packages/cli/src/zosjobs/ZosJobs.definition.ts b/packages/cli/src/zosjobs/ZosJobs.definition.ts index 287b53ffbc..9bcb657aed 100644 --- a/packages/cli/src/zosjobs/ZosJobs.definition.ts +++ b/packages/cli/src/zosjobs/ZosJobs.definition.ts @@ -14,6 +14,7 @@ import { SubmitDefinition } from "./submit/Submit.definition"; import { ViewDefinition } from "./view/View.definition"; import { ListDefinition } from "./list/List.definition"; import { CancelDefinition } from "./cancel/Cancel.definition"; +import { SearchDefinition } from "./search/Search.definition"; import { DeleteDefinition } from "./delete/Delete.definition"; import { DownloadDefinition } from "./download/Download.definition"; import { ZosmfSession } from "@zowe/zosmf-for-zowe-sdk"; @@ -32,7 +33,8 @@ export const definition: ICommandDefinition = { ListDefinition, DeleteDefinition, ModifyDefinition, - CancelDefinition + CancelDefinition, + SearchDefinition ], passOn: [ { diff --git a/packages/cli/src/zosjobs/list/jobs/Jobs.handler.ts b/packages/cli/src/zosjobs/list/jobs/Jobs.handler.ts index 686649b6fe..d425491f7c 100644 --- a/packages/cli/src/zosjobs/list/jobs/Jobs.handler.ts +++ b/packages/cli/src/zosjobs/list/jobs/Jobs.handler.ts @@ -30,8 +30,8 @@ export default class JobsHandler extends ZosmfBaseHandler { public async processCmd(params: IHandlerParameters): Promise { // Obtain the list of jobs - by default uses the session user and * for owner and prefix. - const owner: string = (params.arguments.owner != null) ? params.arguments.owner : null; - const prefix: string = (params.arguments.prefix != null) ? params.arguments.prefix : JobsConstants.DEFAULT_PREFIX; + const owner: string = params.arguments.owner != null ? params.arguments.owner : null; + const prefix: string = params.arguments.prefix != null ? params.arguments.prefix : JobsConstants.DEFAULT_PREFIX; const execData: boolean = params.arguments.execData; const jobs: IJob[] = await GetJobs.getJobsCommon(this.mSession, {owner, prefix, execData}); diff --git a/packages/cli/src/zosjobs/search/Search.definition.ts b/packages/cli/src/zosjobs/search/Search.definition.ts new file mode 100644 index 0000000000..298014fc7a --- /dev/null +++ b/packages/cli/src/zosjobs/search/Search.definition.ts @@ -0,0 +1,28 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ICommandDefinition } from "@zowe/imperative"; +import { JobDefinition } from "./job/Job.definition"; + +import i18nTypings from "../-strings-/en"; + +const strings = (require("../-strings-/en").default as typeof i18nTypings).SEARCH; + +export const SearchDefinition: ICommandDefinition = { + name: "search", + aliases: ["sea"], + type: "group", + summary: strings.SUMMARY, + description: strings.DESCRIPTION, + children: [ + JobDefinition + ] +}; diff --git a/packages/cli/src/zosjobs/search/job/Job.definition.ts b/packages/cli/src/zosjobs/search/job/Job.definition.ts new file mode 100644 index 0000000000..ba2055e40f --- /dev/null +++ b/packages/cli/src/zosjobs/search/job/Job.definition.ts @@ -0,0 +1,81 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ICommandDefinition } from "@zowe/imperative"; + +import i18nTypings from "../../-strings-/en"; + +const strings = (require("../../-strings-/en").default as typeof i18nTypings).SEARCH; + +export const JobDefinition: ICommandDefinition = { + name: "job", + type: "command", + summary: strings.ACTIONS.JOB.SUMMARY, + description: strings.ACTIONS.JOB.DESCRIPTION, + handler: __dirname + "/Job.handler", + profile: { + optional: ["zosmf"] + }, + positionals: [ + { + name: "jobname", + description: strings.ACTIONS.JOB.POSITIONALS.JOBNAME, + type: "string", + required: true + }, + ], + options: [ + { + name: "search-string", + aliases: ["string"], + description: strings.ACTIONS.JOB.OPTIONS.SEARCHSTRING, + type: "string", + defaultValue: undefined, + required: false + }, + { + name: "search-regex", + aliases: ["regex"], + description: strings.ACTIONS.JOB.OPTIONS.SEARCHREGEX, + type: "string", + defaultValue: undefined, + required: false + }, + { + name: "case-insensitive", + aliases: ["ci"], + description: strings.ACTIONS.JOB.OPTIONS.CASEINSENSITIVE, + type: "boolean", + defaultValue: true, + required: false + }, + { + name: "search-limit", + aliases: ["sl"], + description: strings.ACTIONS.JOB.OPTIONS.SEARCHLIMIT, + type: "number", + defaultValue: 100, + required: false + }, + { + name: "file-limit", + aliases: ["fl"], + description: strings.ACTIONS.JOB.OPTIONS.FILELIMIT, + type: "number", + defaultValue: 100, + required: false + } + ], + examples: Object.values(strings.ACTIONS.JOB.EXAMPLES).map((item: any) => ({ + description: item.DESCRIPTION, + options: item.OPTIONS + })) +}; diff --git a/packages/cli/src/zosjobs/search/job/Job.handler.ts b/packages/cli/src/zosjobs/search/job/Job.handler.ts new file mode 100644 index 0000000000..4ec46dcfa9 --- /dev/null +++ b/packages/cli/src/zosjobs/search/job/Job.handler.ts @@ -0,0 +1,64 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { IHandlerParameters } from "@zowe/imperative"; +import { SearchJobs } from "@zowe/zos-jobs-for-zowe-sdk"; +import { ISearchJobsParms } from "@zowe/zos-jobs-for-zowe-sdk"; +import { ZosmfBaseHandler } from "@zowe/zosmf-for-zowe-sdk"; + +/** + * "zos-jobs search job" command handler. Modify a job by name and ID. + * @export + * @class JobHandler + * @implements {ICommandHandler} + */ +export default class JobHandler extends ZosmfBaseHandler { + /** + * Command line arguments passed + * @private + * @type {*} + * @memberof JobHandler + */ + private arguments: any; + + /** + * Command handler process - invoked by the command processor to handle the "zos-jobs search job" + * @param {IHandlerParameters} params - Command handler parameters + * @returns {Promise} - Fulfilled when the command completes successfully OR rejected with imperative error + * @memberof JobHandler + */ + public async processCmd(params: IHandlerParameters): Promise { + this.arguments = params.arguments; + const searchParms: ISearchJobsParms = { jobName : this.arguments.jobname, + caseInsensitive: this.arguments.caseInsensitive, + searchLimit: this.arguments.searchLimit, + fileLimit: this.arguments.fileLimit}; + + if( this.arguments.searchString != undefined) + searchParms.searchString = encodeURI(this.arguments.searchString); + + if(this.arguments.searchRegex != undefined) + searchParms.searchRegex = encodeURI(this.arguments.searchRegex); + + // Get the job details + const dsContentBuf:string = await SearchJobs.searchJobs(this.mSession, searchParms); + + // If no string was found then set the exit code + if(dsContentBuf.length == 0){ + this.data.setExitCode(1); + }else{ + this.data.setExitCode(0); + } + + this.data.setObj(dsContentBuf); + this.console.log(Buffer.from(dsContentBuf)); + } +} diff --git a/packages/cli/src/zosjobs/submit/Submit.shared.handler.ts b/packages/cli/src/zosjobs/submit/Submit.shared.handler.ts index 9daf5a87ae..00c2596f93 100644 --- a/packages/cli/src/zosjobs/submit/Submit.shared.handler.ts +++ b/packages/cli/src/zosjobs/submit/Submit.shared.handler.ts @@ -11,10 +11,10 @@ import { IHandlerParameters, ImperativeError, ITaskWithStatus, TaskProgress, TaskStage } from "@zowe/imperative"; import * as fs from "fs"; -import { ISubmitParms, SubmitJobs, IJob, ISpoolFile } from "@zowe/zos-jobs-for-zowe-sdk"; +import { ISubmitParms, SubmitJobs, IJob, ISpoolFile, ZosJobsMessages } from "@zowe/zos-jobs-for-zowe-sdk"; import { IDownloadOptions, Get } from "@zowe/zos-files-for-zowe-sdk"; import { ZosmfBaseHandler } from "@zowe/zosmf-for-zowe-sdk"; -import getStream = require("get-stream"); +import { text } from "stream/consumers"; /** * "zos-jobs submit data-set" command handler. Submits a job (JCL) contained within a z/OS data set (PS or PDS member). @@ -31,153 +31,170 @@ export default class SharedSubmitHandler extends ZosmfBaseHandler { * @memberof SubmitDataSetHandler */ public async processCmd(params: IHandlerParameters): Promise { - const status: ITaskWithStatus = { - statusMessage: "Submitting job", - percentComplete: TaskProgress.TEN_PERCENT, - stageName: TaskStage.IN_PROGRESS - }; - // Save the needed parameters for convenience - const parms: ISubmitParms = { - jclSource: undefined, - viewAllSpoolContent: this.mArguments.viewAllSpoolContent, - directory: this.mArguments.directory, - extension: this.mArguments.extension, - volume: this.mArguments.volume, - waitForActive: this.mArguments.waitForActive, - waitForOutput: this.mArguments.waitForOutput, - task: status, - jclSymbols: this.mArguments.jclSymbols, - internalReaderFileEncoding: this.mArguments.jobEncoding, - internalReaderLrecl: this.mArguments.jobRecordLength?.toString(), - internalReaderRecfm: this.mArguments.jobRecordFormat - }; - const options: IDownloadOptions = {}; - params.response.progress.startBar({task: status}); - - // Determine the positional parameter specified and invoke the correct API - // TODO: More will be added with additional commands - let sourceType: string; - if (this.mArguments.dataset) { - sourceType = "dataset"; - } else if (this.mArguments.file) { - sourceType = "uss-file"; - } else if (this.mArguments.localFile) { - sourceType = "local-file"; - } else if (params.definition.name === "stdin") { - sourceType = "stdin"; - } - let response: IJob; // Response from Submit Job - let apiObj: any; // API Object to set in the command JSON response - let spoolFilesResponse: ISpoolFile[]; // Response from view all spool content option - let source: any; // The actual JCL source (i.e. data-set name, file name, etc.) - let directory: string = this.mArguments.directory;// Path where to download spool content - - // Process depending on the source type - switch (sourceType) { - - // Submit the JCL from a data set - case "dataset": - - // If the data set is not in catalog and volume option is provided - if (parms.volume) { - options.volume = parms.volume; - - // Get JCL from data set or member - const getJcl = await Get.dataSet(this.mSession, this.mArguments.dataset, options); - source = this.mArguments.dataset; - - apiObj = await SubmitJobs.submitJclString(this.mSession, getJcl.toString(), parms); - if (parms.viewAllSpoolContent) { - spoolFilesResponse = apiObj; + try { + const status: ITaskWithStatus = { + statusMessage: "Submitting job", + percentComplete: TaskProgress.TEN_PERCENT, + stageName: TaskStage.IN_PROGRESS + }; + // Save the needed parameters for convenience + const parms: ISubmitParms = { + jclSource: undefined, + viewAllSpoolContent: this.mArguments.viewAllSpoolContent, + directory: this.mArguments.directory, + extension: this.mArguments.extension, + volume: this.mArguments.volume, + waitForActive: this.mArguments.waitForActive, + waitForOutput: this.mArguments.waitForOutput, + task: status, + jclSymbols: this.mArguments.jclSymbols, + internalReaderFileEncoding: this.mArguments.jobEncoding, + internalReaderLrecl: this.mArguments.jobRecordLength?.toString(), + internalReaderRecfm: this.mArguments.jobRecordFormat + }; + const options: IDownloadOptions = {}; + params.response.progress.startBar({task: status}); + + // Determine the positional parameter specified and invoke the correct API + // TODO: More will be added with additional commands + let sourceType: string; + if (this.mArguments.dataset) { + sourceType = "dataset"; + } else if (this.mArguments.file) { + sourceType = "uss-file"; + } else if (this.mArguments.localFile) { + sourceType = "local-file"; + } else if (params.definition.name === "stdin") { + sourceType = "stdin"; + } + let response: IJob; // Response from Submit Job + let apiObj: any; // API Object to set in the command JSON response + let spoolFilesResponse: ISpoolFile[]; // Response from view all spool content option + let source: any; // The actual JCL source (i.e. data-set name, file name, etc.) + let directory: string = this.mArguments.directory;// Path where to download spool content + + // Process depending on the source type + switch (sourceType) { + + // Submit the JCL from a data set + case "dataset": + + // If the data set is not in catalog and volume option is provided + if (parms.volume) { + options.volume = parms.volume; + + // Get JCL from data set or member + const getJcl = await Get.dataSet(this.mSession, this.mArguments.dataset, options); + source = this.mArguments.dataset; + + apiObj = await SubmitJobs.submitJclString(this.mSession, getJcl.toString(), parms); + if (parms.viewAllSpoolContent) { + spoolFilesResponse = apiObj; + } + + break; + } else { + response = await SubmitJobs.submitJobCommon(this.mSession, {jobDataSet: this.mArguments.dataset, + jclSymbols: this.mArguments.jclSymbols}); + apiObj = await SubmitJobs.checkSubmitOptions(this.mSession, parms, response); + source = this.mArguments.dataset; + + if (parms.viewAllSpoolContent) { + spoolFilesResponse = apiObj; + } } break; - } else { - response = await SubmitJobs.submitJobCommon(this.mSession, {jobDataSet: this.mArguments.dataset, + // Submit JCL from a USS file + case "uss-file": + response = await SubmitJobs.submitJobCommon(this.mSession, {jobUSSFile: this.mArguments.file, jclSymbols: this.mArguments.jclSymbols}); apiObj = await SubmitJobs.checkSubmitOptions(this.mSession, parms, response); - source = this.mArguments.dataset; + source = this.mArguments.ussfile; if (parms.viewAllSpoolContent) { spoolFilesResponse = apiObj; } - } - - break; - // Submit JCL from a USS file - case "uss-file": - response = await SubmitJobs.submitJobCommon(this.mSession, {jobUSSFile: this.mArguments.file, - jclSymbols: this.mArguments.jclSymbols}); - apiObj = await SubmitJobs.checkSubmitOptions(this.mSession, parms, response); - source = this.mArguments.ussfile; - - if (parms.viewAllSpoolContent) { - spoolFilesResponse = apiObj; - } - break; - // Submit the JCL from a local file - case "local-file": { - parms.jclSource = this.mArguments.localFile; - const JclString = fs.readFileSync(this.mArguments.localFile).toString(); - apiObj = await SubmitJobs.submitJclString(this.mSession, JclString, parms); - source = this.mArguments.localFile; - if (parms.viewAllSpoolContent) { - spoolFilesResponse = apiObj; + break; + // Submit the JCL from a local file + case "local-file": { + parms.jclSource = this.mArguments.localFile; + let JclString: string; + try { + JclString = fs.readFileSync(this.mArguments.localFile).toString(); + } catch (err) { + throw new ImperativeError({ + msg: ZosJobsMessages.nodeJsFsError.message, + additionalDetails: err.toString(), + causeErrors: err + }); + } + apiObj = await SubmitJobs.submitJclString(this.mSession, JclString, parms); + source = this.mArguments.localFile; + if (parms.viewAllSpoolContent) { + spoolFilesResponse = apiObj; + } + break; } - break; - } - // Submit the JCL piped in on stdin - case "stdin": { - const Jcl = await getStream(params.stdin); - apiObj = await SubmitJobs.submitJclString(this.mSession, Jcl, parms); - source = "stdin"; - if (parms.viewAllSpoolContent) { - spoolFilesResponse = apiObj; + // Submit the JCL piped in on stdin + case "stdin": { + const Jcl = await text(params.stdin); + apiObj = await SubmitJobs.submitJclString(this.mSession, Jcl, parms); + source = "stdin"; + if (parms.viewAllSpoolContent) { + spoolFilesResponse = apiObj; + } + break; } - break; + default: + throw new ImperativeError({ + msg: `Internal submit error: Unable to determine the JCL source. ` + + `Please contact support.`, + additionalDetails: JSON.stringify(params) + }); } - default: - throw new ImperativeError({ - msg: `Internal submit error: Unable to determine the JCL source. ` + - `Please contact support.`, - additionalDetails: JSON.stringify(params) - }); - } - // Print the response to the command - if (spoolFilesResponse == null) { - params.response.format.output({ - fields: ["jobid", "retcode", "jobname", "status"], - output: apiObj, - format: "object" - }); - // Set the API object to the correct - this.data.setObj(apiObj); - - // Print data from spool content - } else { - for (const spoolFile of spoolFilesResponse) { - if (spoolFile.procName != null && spoolFile.procName.length > 0) { - this.console.log("Spool file: %s (ID #%d, Step: %s, ProcStep: %s)", - spoolFile.ddName, spoolFile.id, spoolFile.stepName, spoolFile.procName); - } else { - this.console.log("Spool file: %s (ID #%d, Step: %s)", - spoolFile.ddName, spoolFile.id, spoolFile.stepName); + // Print the response to the command + if (spoolFilesResponse == null) { + params.response.format.output({ + fields: ["jobid", "retcode", "jobname", "status"], + output: apiObj, + format: "object" + }); + // Set the API object to the correct + this.data.setObj(apiObj); + + // Print data from spool content + } else { + for (const spoolFile of spoolFilesResponse) { + if (spoolFile.procName != null && spoolFile.procName.length > 0) { + this.console.log("Spool file: %s (ID #%d, Step: %s, ProcStep: %s)", + spoolFile.ddName, spoolFile.id, spoolFile.stepName, spoolFile.procName); + } else { + this.console.log("Spool file: %s (ID #%d, Step: %s)", + spoolFile.ddName, spoolFile.id, spoolFile.stepName); + } + this.console.log(spoolFile.data); } - this.console.log(spoolFile.data); - } - // Set the API object to the correct - this.data.setObj(spoolFilesResponse); - } + // Set the API object to the correct + this.data.setObj(spoolFilesResponse); + } - // Print path where spool content was downloaded - if (directory != null && spoolFilesResponse == null) { - directory = directory.includes("./") ? directory : `./${directory}`; - params.response.console.log(`Successfully downloaded output to ${directory}/${apiObj.jobid}`); + // Print path where spool content was downloaded + if (directory != null && spoolFilesResponse == null) { + directory = directory.includes("./") ? directory : `./${directory}`; + params.response.console.log(`Successfully downloaded output to ${directory}/${apiObj.jobid}`); + } + params.response.progress.endBar(); + this.data.setMessage(`Submitted JCL contained in "${sourceType}": "${source}"`); + }catch (err){ + if (err instanceof ImperativeError){ + throw err; + } else { + throw new ImperativeError({msg: err.message, causeErrors: err}); + } } - params.response.progress.endBar(); - this.data.setMessage(`Submitted JCL contained in "${sourceType}": "${source}"`); } -} +} \ No newline at end of file diff --git a/packages/cli/src/zosmf/check/Check.definition.ts b/packages/cli/src/zosmf/check/Check.definition.ts index ee5990437f..a36a64b0fa 100644 --- a/packages/cli/src/zosmf/check/Check.definition.ts +++ b/packages/cli/src/zosmf/check/Check.definition.ts @@ -15,8 +15,9 @@ import { StatusDefinition } from "./status/Status.definition"; export const CheckCommand: ICommandDefinition = { name: "check", type: "group", + summary: "Check z/OSMF status on a specified system", description: "Confirm that z/OSMF is running on a specified system " + - "and gather information about the z/OSMF server for diagnostic purposes. ", + "and gather information about the z/OSMF server for diagnostic purposes.", children: [ StatusDefinition ] diff --git a/packages/cli/src/zosmf/check/status/Status.definition.ts b/packages/cli/src/zosmf/check/status/Status.definition.ts index a4fc9b744c..f85bb10981 100644 --- a/packages/cli/src/zosmf/check/status/Status.definition.ts +++ b/packages/cli/src/zosmf/check/status/Status.definition.ts @@ -14,6 +14,7 @@ import { ZosmfSession } from "@zowe/zosmf-for-zowe-sdk"; export const StatusDefinition: ICommandDefinition = { name: "status", + summary: "Check z/OSMF status on a specified system", description: "Confirm that z/OSMF is running on a system specified in your profile and gather " + "information about the z/OSMF server for diagnostic purposes. The command outputs properties " + "of the z/OSMF server such as version, hostname, and installed plug-ins.", diff --git a/packages/cli/src/zosmf/list/List.definition.ts b/packages/cli/src/zosmf/list/List.definition.ts index 72181bb241..0645cbc435 100644 --- a/packages/cli/src/zosmf/list/List.definition.ts +++ b/packages/cli/src/zosmf/list/List.definition.ts @@ -15,6 +15,7 @@ import { SystemsDefinition } from "./systems/Systems.definition"; export const ListCommand: ICommandDefinition = { name: "list", type: "group", + summary: "Obtain a list of systems that are defined to a z/OSMF instance", description: "Obtain a list of systems that are defined to a z/OSMF instance.", children: [ SystemsDefinition diff --git a/packages/cli/src/zosmf/list/systems/Systems.definition.ts b/packages/cli/src/zosmf/list/systems/Systems.definition.ts index 94c8f8f0d8..82b8147276 100644 --- a/packages/cli/src/zosmf/list/systems/Systems.definition.ts +++ b/packages/cli/src/zosmf/list/systems/Systems.definition.ts @@ -14,6 +14,7 @@ import { ZosmfSession } from "@zowe/zosmf-for-zowe-sdk"; export const SystemsDefinition: ICommandDefinition = { name: "systems", + summary: "Obtain a list of systems that are defined to a z/OSMF instance", description: "Obtain a list of systems that are defined to a z/OSMF instance.", type: "command", handler: __dirname + "/Systems.handler", diff --git a/packages/cli/src/zostso/constants/ZosTso.constants.ts b/packages/cli/src/zostso/constants/ZosTso.constants.ts deleted file mode 100644 index e70a9bdce1..0000000000 --- a/packages/cli/src/zostso/constants/ZosTso.constants.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { TsoProfileConstants } from "@zowe/zos-tso-for-zowe-sdk"; - -/** - * @deprecated Please use this constant from the @zowe/zos-tso-for-zowe-sdk - */ -export const TSO_OPTION_GROUP = TsoProfileConstants.TSO_OPTION_GROUP; - -/** - * @deprecated Please use this constant from the @zowe/zos-tso-for-zowe-sdk - */ -export const TSO_OPTION_ACCOUNT = TsoProfileConstants.TSO_OPTION_ACCOUNT; - -/** - * @deprecated Please use this constant from the @zowe/zos-tso-for-zowe-sdk - */ -export const TSO_OPTION_ACCOUNT_PROFILE = TsoProfileConstants.TSO_OPTION_ACCOUNT_PROFILE; - -/** - * @deprecated Please use this constant from the @zowe/zos-tso-for-zowe-sdk - */ -export const TSO_OPTION_CHAR_SET = TsoProfileConstants.TSO_OPTION_CHAR_SET; - -/** - * @deprecated Please use this constant from the @zowe/zos-tso-for-zowe-sdk - */ -export const TSO_OPTION_CODE_PAGE = TsoProfileConstants.TSO_OPTION_CODE_PAGE; - -/** - * @deprecated Please use this constant from the @zowe/zos-tso-for-zowe-sdk - */ -export const TSO_OPTION_COLUMNS = TsoProfileConstants.TSO_OPTION_COLUMNS; - -/** - * @deprecated Please use this constant from the @zowe/zos-tso-for-zowe-sdk - */ -export const TSO_OPTION_LOGON_PROCEDURE = TsoProfileConstants.TSO_OPTION_LOGON_PROCEDURE; - -/** - * @deprecated Please use this constant from the @zowe/zos-tso-for-zowe-sdk - */ -export const TSO_OPTION_REGION_SIZE = TsoProfileConstants.TSO_OPTION_REGION_SIZE; - -/** - * @deprecated Please use this constant from the @zowe/zos-tso-for-zowe-sdk - */ -export const TSO_OPTION_ROWS = TsoProfileConstants.TSO_OPTION_ROWS; - -/** - * @deprecated Please use this constant from the @zowe/zos-tso-for-zowe-sdk - */ -export const TSO_PROFILE_OPTIONS = TsoProfileConstants.TSO_PROFILE_OPTIONS; diff --git a/packages/cli/src/zostso/start/address-space/AddressSpace.definition.ts b/packages/cli/src/zostso/start/address-space/AddressSpace.definition.ts index 63ef0ccd5a..ecb79b8789 100644 --- a/packages/cli/src/zostso/start/address-space/AddressSpace.definition.ts +++ b/packages/cli/src/zostso/start/address-space/AddressSpace.definition.ts @@ -15,6 +15,7 @@ import { TsoProfileConstants } from "@zowe/zos-tso-for-zowe-sdk"; export const AddressSpaceDefinition: ICommandDefinition = { name: "address-space", aliases: ["as"], + summary: "Start a TSO address space", description: "Start a TSO address space, from which " + "you will receive a token (a.k.a 'servlet-key') for further address space interaction " + "(e.g. termination).", diff --git a/packages/cli/src/zostso/stop/address-space/AddressSpace.definition.ts b/packages/cli/src/zostso/stop/address-space/AddressSpace.definition.ts index c83fe56561..08d5323b1c 100644 --- a/packages/cli/src/zostso/stop/address-space/AddressSpace.definition.ts +++ b/packages/cli/src/zostso/stop/address-space/AddressSpace.definition.ts @@ -14,6 +14,7 @@ import { ICommandDefinition } from "@zowe/imperative"; export const AddressSpaceDefinition: ICommandDefinition = { name: "address-space", aliases: ["as"], + summary: "Stop a TSO address space", description: "Stop a TSO address space, from which " + "you previously started and received a token (a.k.a 'servlet-key').", type: "command", diff --git a/packages/cli/src/zosuss/issue/ssh/Ssh.definition.ts b/packages/cli/src/zosuss/issue/ssh/Ssh.definition.ts index 7c51d75e6d..075d05fa01 100644 --- a/packages/cli/src/zosuss/issue/ssh/Ssh.definition.ts +++ b/packages/cli/src/zosuss/issue/ssh/Ssh.definition.ts @@ -14,6 +14,7 @@ import { ICommandDefinition } from "@zowe/imperative"; export const SshDefinition: ICommandDefinition = { name: "command", aliases: ["cmd", "ssh"], + summary: "Issue a z/OS USS command", description: "Issue a z/OS USS command\n\n" + "Note: The common CLI 'Base Connection Options' of token-type and token-value are not applicable to " + "the ssh command, since the ssh service is not accessible through APIML.", @@ -21,14 +22,14 @@ export const SshDefinition: ICommandDefinition = { type: "command", positionals: [{ name: "command", - description: "z/OS USS command to issue", + description: "z/OS USS command to issue.", type: "string", required: true }], options: [ { name: "cwd", - description: "Working directory in which to execute the command", + description: "Working directory in which to execute the command.", type: "string" }], profile: { diff --git a/packages/cli/src/zosuss/issue/ssh/Ssh.handler.ts b/packages/cli/src/zosuss/issue/ssh/Ssh.handler.ts index 83c9b53a81..0702c4567c 100644 --- a/packages/cli/src/zosuss/issue/ssh/Ssh.handler.ts +++ b/packages/cli/src/zosuss/issue/ssh/Ssh.handler.ts @@ -37,4 +37,4 @@ export default class Handler extends SshBaseHandler { public handleStdout(data: string) { this.parameters.response.console.log(Buffer.from(data)); } -} +} \ No newline at end of file diff --git a/packages/cli/typedoc.json b/packages/cli/typedoc.json index 2b97359f2c..b15f87adc5 100644 --- a/packages/cli/typedoc.json +++ b/packages/cli/typedoc.json @@ -1,5 +1,6 @@ { "out": "./docs/typedoc/", - "exclude": "**/__tests__/**", + "exclude": ["**/__tests__/**"], + "entryPoints": ["src/index.ts"], "cleanOutputDir": true } \ No newline at end of file diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index a74d73be17..f9acb59e71 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -2,6 +2,47 @@ All notable changes to the Zowe core SDK package will be documented in this file. +## Recent Changes + +- Update: Final prerelease + +## `8.0.0-next.202406111958` + +- BugFix: Deprecated the IHeaderContent interface - use `IHeaderContent` from `@zowe/imperative`. [#2083](https://github.com/zowe/zowe-cli/issues/2083) + +## `8.0.0-next.202406061600` + +- Enhancement: Modified Services.ts to have commented properties end with commas. [#1049](https://github.com/zowe/zowe-cli/issues/1049) + +## `8.0.0-next.202403041352` + +- BugFix: Updated engine to Node 18.12.0. [#2074](https://github.com/zowe/zowe-cli/pull/2074) +- LTS Breaking: Removed the file ProfileUtils.ts which contains the following obsolete V1 profile functions: + - getDefaultProfile + - getZoweDir - moved to ProfileInfo.getZoweDir + +## `8.0.0-next.202402261705` + +- BugFix: Updated additional dependencies for technical currency. [#2061](https://github.com/zowe/zowe-cli/pull/2061) +- BugFix: Updated engine to Node 16.7.0. [#2061](https://github.com/zowe/zowe-cli/pull/2061) + +## `8.0.0-next.202402211923` + +- BugFix: Updated dependencies for technical currency. [#2057](https://github.com/zowe/zowe-cli/pull/2057) + +## `8.0.0-next.202401191954` + +- LTS Breaking: Removed all 'profiles' commands, since they only worked with now-obsolete V1 profiles. +- BugFix: Include text from a REST response's causeErrors.message property in error messages. + +## `8.0.0-next.202311282012` + +- LTS Breaking: Unpinned dependency versions to allow for patch/minor version updates for dependencies [#1968](https://github.com/zowe/zowe-cli/issues/1968) + +## `8.0.0-next.202311132045` + +- Major: First major version bump for V3 + ## `7.25.2` - Enhancement: Modified Services.ts to have commented properties end with commas. [#1049](https://github.com/zowe/zowe-cli/issues/1049) @@ -25,7 +66,7 @@ All notable changes to the Zowe core SDK package will be documented in this file ## `7.17.0` - Enhancement: Set properties for z/OSMF REST errors for use in a more user-friendly format with the ZOWE_V3_ERR_FORMAT environment variable. [zowe-cli#935](https://github.com/zowe/zowe-cli/issues/935) -- + ## `7.16.5` - BugFix: Fixed confusing error message "Token is not valid or expired" when APIML token is used to connect direct-to-service with `ZosmfRestClient`. [Imperative #978](https://github.com/zowe/imperative/issues/978) diff --git a/packages/core/__tests__/apiml/__unit__/allPluginCfgPropsMock.json b/packages/core/__tests__/apiml/__unit__/allPluginCfgPropsMock.json index 29f97d35fb..eec0405588 100644 --- a/packages/core/__tests__/apiml/__unit__/allPluginCfgPropsMock.json +++ b/packages/core/__tests__/apiml/__unit__/allPluginCfgPropsMock.json @@ -6,7 +6,6 @@ "commandModuleGlobs": [ "**/*.definition!(.d).*s" ], - "pluginHealthCheck": "./lib/HealthCheck.handler", "rootCommandDescription": "CA Endevor SCM plug-in for listing Endevor environment information, working with elements and packages located in specified Endevor instance.", "envVariablePrefix": "ENDEVOR", "defaultHome": "C:\\Users\\ej608771/.endevor", @@ -19,7 +18,7 @@ } ], "appLogging": { - "logFile": "zowe/logs/zowe-endevor.log" + "logFile": "logs/zowe-endevor.log" } }, "secondaryTextColor": "yellow", @@ -309,7 +308,6 @@ "commandModuleGlobs": [ "**/cli/*/*.definition!(.d).*s" ], - "pluginHealthCheck": "C:\\Users\\ej608771\\.zowe\\plugins\\installed\\node_modules\\@broadcom\\jclcheck-for-zowe-cli\\lib/healthCheck.handler", "pluginSummary": "JCLCheck plugin", "pluginAliases": [ "jck" diff --git a/packages/core/__tests__/apiml/__unit__/cliImpConfigMock.json b/packages/core/__tests__/apiml/__unit__/cliImpConfigMock.json index 39b4b39e43..eec9347f8a 100644 --- a/packages/core/__tests__/apiml/__unit__/cliImpConfigMock.json +++ b/packages/core/__tests__/apiml/__unit__/cliImpConfigMock.json @@ -16,7 +16,7 @@ "webHelpLogoImgPath": "C:\\ourstuff\\repos\\zowe-cli\\packages\\cli\\web-help-logo.png", "logging": { "appLogging": { - "logFile": "zowe/logs/zowe.log", + "logFile": "logs/zowe.log", "apiName": "app", "category": "app" }, diff --git a/packages/core/__tests__/auth/__unit__/Login.apiml.unit.test.ts b/packages/core/__tests__/auth/__unit__/Login.apiml.unit.test.ts index f353251229..7cecf898cf 100644 --- a/packages/core/__tests__/auth/__unit__/Login.apiml.unit.test.ts +++ b/packages/core/__tests__/auth/__unit__/Login.apiml.unit.test.ts @@ -11,7 +11,7 @@ import { Login } from "../../../src/auth/Login"; import { ZosmfRestClient } from "../../../src/rest/ZosmfRestClient"; -import { ImperativeError, NextVerFeatures, RestConstants } from "@zowe/imperative"; +import { ImperativeError, RestConstants } from "@zowe/imperative"; const goodResponse: any = { statusCode: RestConstants.HTTP_STATUS_204 @@ -32,13 +32,6 @@ const fakeSession: any = { describe("Auth Login APIML unit tests", () => { - beforeEach(() => { - /* This avoids having to mock ImperativeConfig.envVariablePrefix. - * Unless the choice below is overridden, tests will use our legacy format for errors. - */ - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(false); - }); - describe("Positive tests", () => { it("should allow users to call apimlLogin with correct parameters", async () => { ZosmfRestClient.prototype.request = jest.fn(); @@ -65,7 +58,9 @@ describe("Auth Login APIML unit tests", () => { } expect(caughtError).toBeDefined(); expect(caughtError instanceof ImperativeError).toEqual(true); - expect(caughtError.mDetails).toMatchSnapshot(); + const errDetailString = caughtError.mDetails.toString(); + expect(errDetailString).toContain("Error: REST API Failure with HTTP(S) status 401"); + expect(errDetailString).toContain("This operation requires authentication"); }); }); diff --git a/packages/core/__tests__/auth/__unit__/Logout.apiml.unit.test.ts b/packages/core/__tests__/auth/__unit__/Logout.apiml.unit.test.ts index 82589feb72..92ffbffad6 100644 --- a/packages/core/__tests__/auth/__unit__/Logout.apiml.unit.test.ts +++ b/packages/core/__tests__/auth/__unit__/Logout.apiml.unit.test.ts @@ -11,7 +11,7 @@ import { Logout } from "../../../src/auth/Logout"; import { ZosmfRestClient } from "../../../src/rest/ZosmfRestClient"; -import { ImperativeError, NextVerFeatures, RestConstants } from "@zowe/imperative"; +import { ImperativeError, RestConstants } from "@zowe/imperative"; const goodResponse: any = { statusCode: RestConstants.HTTP_STATUS_204 @@ -49,13 +49,6 @@ const fakeSession: any = { describe("Auth Logout APIML unit tests", () => { - beforeEach(() => { - /* This avoids having to mock ImperativeConfig.envVariablePrefix. - * Unless overridden, tests will use our legacy format for errors. - */ - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(false); - }); - describe("Positive tests", () => { it("should allow users to call apimlLogout with correct parameters", async () => { ZosmfRestClient.prototype.request = jest.fn(); diff --git a/packages/core/__tests__/auth/__unit__/__snapshots__/Login.apiml.unit.test.ts.snap b/packages/core/__tests__/auth/__unit__/__snapshots__/Login.apiml.unit.test.ts.snap deleted file mode 100644 index d576559c55..0000000000 --- a/packages/core/__tests__/auth/__unit__/__snapshots__/Login.apiml.unit.test.ts.snap +++ /dev/null @@ -1,17 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Auth Login APIML unit tests Error handling tests - HTTP 401 should be able to raise an error with HTTP 401 1`] = ` -[Error: This operation requires authentication. - -z/OSMF REST API Error: -REST API Failure with HTTP(S) status 401 - -Host: undefined -Port: undefined -Base Path: undefined -Resource: undefined -Request: undefined -Headers: undefined -Payload: undefined -] -`; diff --git a/packages/core/__tests__/rest/__unit__/ZosmfRestClient.unit.test.ts b/packages/core/__tests__/rest/__unit__/ZosmfRestClient.unit.test.ts index e566b660d0..b6495ffc59 100644 --- a/packages/core/__tests__/rest/__unit__/ZosmfRestClient.unit.test.ts +++ b/packages/core/__tests__/rest/__unit__/ZosmfRestClient.unit.test.ts @@ -11,17 +11,10 @@ import { ZosmfHeaders } from "../../../src/rest/ZosmfHeaders"; import { ZosmfRestClient } from "../../../src/rest/ZosmfRestClient"; -import { IImperativeError, NextVerFeatures, RestConstants, SessConstants, Session } from "@zowe/imperative"; +import { IImperativeError, RestConstants, SessConstants, Session } from "@zowe/imperative"; describe("ZosmfRestClient tests", () => { - beforeEach(() => { - /* This avoids having to mock ImperativeConfig.envVariablePrefix. - * Unless the choice below is overridden, tests will use our legacy format for errors. - */ - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(false); - }); - it("should append the csrf header to all requests", () => { const zosmfRestClient = new ZosmfRestClient(new Session({ hostname: "dummy" })); expect((zosmfRestClient as any).appendHeaders([])).toMatchObject([ @@ -40,30 +33,15 @@ describe("ZosmfRestClient tests", () => { shouldNotDelete: shouldNotDeleteMessage }) }; - const processedError = ((zosmfRestClient as any).processError(error)); - expect(processedError.msg).toContain(shouldNotDeleteMessage); + const processedError = (zosmfRestClient as any).processError(error); + expect(processedError.causeErrors).not.toContain(shouldDeleteMessage); + expect(processedError.causeErrors).toContain(shouldNotDeleteMessage); expect(processedError.msg.indexOf()).toEqual(-1); }); describe("Authentication errors", () => { - it("should handle error for basic auth", () => { - const zosmfRestClient = new ZosmfRestClient(new Session({ - hostname: "dummy", - type: SessConstants.AUTH_TYPE_BASIC, - user: "fakeUser", - password: "fakePass" - })); - (zosmfRestClient as any).mResponse = { - statusCode: RestConstants.HTTP_STATUS_401 - }; - const error: IImperativeError = { msg: "hello" }; - const processedError = ((zosmfRestClient as any).processError(error)); - expect(processedError.msg).toContain("This operation requires authentication."); - expect(processedError.additionalDetails).toContain("Username or password are not valid or expired."); - }); - it("should handle basic auth error with empty string causeErrors using V3_ERR_FORMAT", () => { - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(true); + it("should handle basic auth error with empty string causeErrors", () => { const zosmfRestClient = new ZosmfRestClient(new Session({ hostname: "dummy", type: SessConstants.AUTH_TYPE_BASIC, @@ -82,7 +60,7 @@ describe("ZosmfRestClient tests", () => { 'Allow Unauth Cert: true' + '}' }; - const processedError = ((zosmfRestClient as any).processError(error)); + const processedError = (zosmfRestClient as any).processError(error); expect(processedError.msg).toContain("Rest API failure with HTTP(S) status 401"); expect(processedError.msg).toContain("This operation requires authentication."); expect(processedError.msg).toContain("Username or password are not valid or expired."); @@ -93,8 +71,7 @@ describe("ZosmfRestClient tests", () => { expect(processedError.additionalDetails).toContain("Allow Unauth Cert: true"); }); - it("should handle basic auth error with JSON causeErrors using V3_ERR_FORMAT", () => { - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(true); + it("should handle basic auth error with JSON causeErrors", () => { const zosmfRestClient = new ZosmfRestClient(new Session({ hostname: "dummy", type: SessConstants.AUTH_TYPE_BASIC, @@ -116,7 +93,7 @@ describe("ZosmfRestClient tests", () => { 'Allow Unauth Cert: true' + '}' }; - const processedError = ((zosmfRestClient as any).processError(error)); + const processedError = (zosmfRestClient as any).processError(error); expect(processedError.msg).toContain("Rest API failure with HTTP(S) status 401"); expect(processedError.msg).toContain("This operation requires authentication."); expect(processedError.msg).toContain("Username or password are not valid or expired."); @@ -129,23 +106,6 @@ describe("ZosmfRestClient tests", () => { }); it("should handle error for token auth", () => { - const zosmfRestClient = new ZosmfRestClient(new Session({ - hostname: "dummy", - type: SessConstants.AUTH_TYPE_TOKEN, - tokenType: SessConstants.TOKEN_TYPE_JWT, - tokenValue: "fakeToken" - })); - (zosmfRestClient as any).mResponse = { - statusCode: RestConstants.HTTP_STATUS_401 - }; - const error: IImperativeError = { msg: "hello" }; - const processedError = ((zosmfRestClient as any).processError(error)); - expect(processedError.msg).toContain("This operation requires authentication."); - expect(processedError.additionalDetails).toContain("Token is not valid or expired."); - }); - - it("should handle error for token auth using V3_ERR_FORMAT", () => { - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(true); const zosmfRestClient = new ZosmfRestClient(new Session({ hostname: "dummy", type: SessConstants.AUTH_TYPE_TOKEN, @@ -156,7 +116,7 @@ describe("ZosmfRestClient tests", () => { statusCode: RestConstants.HTTP_STATUS_401 }; const error: IImperativeError = { msg: "Fake token error" }; - const processedError = ((zosmfRestClient as any).processError(error)); + const processedError = (zosmfRestClient as any).processError(error); expect(processedError.msg).toContain("Fake token error"); expect(processedError.msg).toContain("This operation requires authentication."); expect(processedError.msg).toContain("Token is not valid or expired"); @@ -167,23 +127,6 @@ describe("ZosmfRestClient tests", () => { }); it("should handle error for APIML token auth and missing base path", () => { - const zosmfRestClient = new ZosmfRestClient(new Session({ - hostname: "dummy", - type: SessConstants.AUTH_TYPE_TOKEN, - tokenType: SessConstants.TOKEN_TYPE_APIML, - tokenValue: "fakeToken" - })); - (zosmfRestClient as any).mResponse = { - statusCode: RestConstants.HTTP_STATUS_401 - }; - const error: IImperativeError = { msg: "hello" }; - const processedError = ((zosmfRestClient as any).processError(error)); - expect(processedError.msg).toContain("This operation requires authentication."); - expect(processedError.additionalDetails).not.toContain("Token is not valid or expired."); - }); - - it("should handle error for APIML token auth and missing base path using V3_ERR_FORMAT", () => { - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(true); const zosmfRestClient = new ZosmfRestClient(new Session({ hostname: "dummy", type: SessConstants.AUTH_TYPE_TOKEN, @@ -194,7 +137,7 @@ describe("ZosmfRestClient tests", () => { statusCode: RestConstants.HTTP_STATUS_401 }; const error: IImperativeError = { msg: "Fake token error" }; - const processedError = ((zosmfRestClient as any).processError(error)); + const processedError = (zosmfRestClient as any).processError(error); expect(processedError.msg).toContain("Fake token error"); expect(processedError.msg).toContain("This operation requires authentication."); expect(processedError.msg).toContain("Token type \"apimlAuthenticationToken\" requires base path to be defined."); @@ -204,23 +147,6 @@ describe("ZosmfRestClient tests", () => { }); it("should handle error for cert auth", () => { - const zosmfRestClient = new ZosmfRestClient(new Session({ - hostname: "dummy", - type: SessConstants.AUTH_TYPE_CERT_PEM, - cert: "fakeCert", - certKey: "fakeKey" - })); - (zosmfRestClient as any).mResponse = { - statusCode: RestConstants.HTTP_STATUS_401 - }; - const error: IImperativeError = { msg: "hello" }; - const processedError = ((zosmfRestClient as any).processError(error)); - expect(processedError.msg).toContain("This operation requires authentication."); - expect(processedError.additionalDetails).toContain("Certificate is not valid or expired."); - }); - - it("should handle error for cert auth using V3_ERR_FORMAT", () => { - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(true); const zosmfRestClient = new ZosmfRestClient(new Session({ hostname: "dummy", type: SessConstants.AUTH_TYPE_CERT_PEM, @@ -231,7 +157,7 @@ describe("ZosmfRestClient tests", () => { statusCode: RestConstants.HTTP_STATUS_401 }; const error: IImperativeError = { msg: "Bad Cert" }; - const processedError = ((zosmfRestClient as any).processError(error)); + const processedError = (zosmfRestClient as any).processError(error); expect(processedError.msg).toContain("Bad Cert"); expect(processedError.msg).toContain("This operation requires authentication."); expect(processedError.msg).toContain("Certificate is not valid or expired."); diff --git a/packages/core/__tests__/utils/__integration__/ProfileUtils.integration.test.ts b/packages/core/__tests__/utils/__integration__/ProfileUtils.integration.test.ts deleted file mode 100644 index dfc0d0ad3d..0000000000 --- a/packages/core/__tests__/utils/__integration__/ProfileUtils.integration.test.ts +++ /dev/null @@ -1,175 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - - -import * as imperative from "@zowe/imperative"; -import * as profileUtils from "../../../src/utils/ProfileUtils"; -import { ITestEnvironment, runCliScript } from "@zowe/cli-test-utils"; -import { TestEnvironment } from "../../../../../__tests__/__src__/environment/TestEnvironment"; -import { ITestPropertiesSchema } from "../../../../../__tests__/__src__/properties/ITestPropertiesSchema"; - -const fs = require("fs"); - -const fakeServiceProfile: imperative.IProfile = { - name: "fakeServiceProfile", - type: "zosmf", - host: "fakeHostService" -}; - -const fakeBaseProfile: imperative.IProfile = { - name: "fakeBaseProfile", - type: "base", - host: "fakeHostBase" -}; - -const fakeProfileMissingInformation: imperative.IProfile = { - name: "fakeServiceProfile", - type: "zosmf", - host: undefined -}; - -// Test Environment populated in the beforeAll(); -let TEST_ENVIRONMENT: ITestEnvironment; - -describe("ProfileUtils", () => { - describe("getDefaultProfile", () => { - beforeAll(async () => { - TEST_ENVIRONMENT = await TestEnvironment.setUp({ - testName: "core_utils_get_default_profile", - skipProperties: true - }); - - // We need the meta YAML files for the ProfileManager to initialize, so create dummy profiles to supply them - runCliScript(__dirname + "/__scripts__/create_profile.sh", TEST_ENVIRONMENT, - ["zosmf", "fakeServiceProfile", "--host fake --dd"]); - runCliScript(__dirname + "/__scripts__/create_profile.sh", TEST_ENVIRONMENT, - ["base", "fakeBaseProfile", "--host fake --dd"]); - process.env.ZOWE_CLI_HOME = TEST_ENVIRONMENT.workingDir; - }); - beforeEach(() => { - jest.resetAllMocks(); - - // Pretend that we have no team config - Object.defineProperty(imperative.ImperativeConfig.instance, "config", { - configurable: true, - get: jest.fn(() => { - return { - exists: false - }; - }) - }); - }); - afterAll(async () => { - runCliScript(__dirname + "/__scripts__/delete_profile.sh", TEST_ENVIRONMENT, ["zosmf", "fakeServiceProfile"]); - runCliScript(__dirname + "/__scripts__/delete_profile.sh", TEST_ENVIRONMENT, ["base", "fakeBaseProfile"]); - await TestEnvironment.cleanUp(TEST_ENVIRONMENT); - }); - it("Should return a service profile", async() => { - const profileManagerSpy = jest.spyOn(imperative.CliProfileManager.prototype, "load") - .mockResolvedValueOnce({ profile: fakeServiceProfile } as any); - let error; - let profile: imperative.IProfile; - try { - profile = await profileUtils.getDefaultProfile("zosmf", false); - } catch (err) { - error = err; - } - expect(error).not.toBeDefined(); - expect(profileManagerSpy).toHaveBeenCalledTimes(1); - expect(profile).toEqual(fakeServiceProfile); - }); - it("Should return a service profile even though base is missing", async() => { - const profileManagerSpy = jest.spyOn(imperative.CliProfileManager.prototype, "load") - .mockResolvedValueOnce({ profile: fakeServiceProfile } as any) - .mockResolvedValueOnce({ profile: undefined } as any); - let error; - let profile: imperative.IProfile; - try { - profile = await profileUtils.getDefaultProfile("zosmf", true); - } catch (err) { - error = err; - } - expect(error).not.toBeDefined(); - expect(profileManagerSpy).toHaveBeenCalledTimes(2); - expect(profile).toEqual(fakeServiceProfile); - }); - it("Should return a base profile", async() => { - const profileManagerSpy = jest.spyOn(imperative.CliProfileManager.prototype, "load") - .mockResolvedValueOnce({ profile: undefined } as any) - .mockResolvedValueOnce({ profile: fakeBaseProfile } as any); - let error; - let profile: imperative.IProfile; - try { - profile = await profileUtils.getDefaultProfile("zosmf", true); - } catch (err) { - error = err; - } - expect(error).not.toBeDefined(); - expect(profileManagerSpy).toHaveBeenCalledTimes(2); - expect(profile).toEqual(fakeBaseProfile); - }); - it("Should return a service profile even though base was specified", async() => { - const profileManagerSpy = jest.spyOn(imperative.CliProfileManager.prototype, "load") - .mockResolvedValueOnce({ profile: fakeServiceProfile } as any) - .mockResolvedValueOnce({ profile: fakeBaseProfile } as any); - let error; - let profile: imperative.IProfile; - try { - profile = await profileUtils.getDefaultProfile("zosmf", true); - } catch (err) { - error = err; - } - expect(error).not.toBeDefined(); - expect(profileManagerSpy).toHaveBeenCalledTimes(2); - expect(profile).toEqual(fakeServiceProfile); - }); - it("Should properly combine profiles", async() => { - const profileManagerSpy = jest.spyOn(imperative.CliProfileManager.prototype, "load") - .mockResolvedValueOnce({ profile: fakeProfileMissingInformation } as any) - .mockResolvedValueOnce({ profile: fakeBaseProfile } as any); - let error; - let profile: imperative.IProfile; - try { - profile = await profileUtils.getDefaultProfile("zosmf", true); - } catch (err) { - error = err; - } - expect(error).not.toBeDefined(); - expect(profileManagerSpy).toHaveBeenCalledTimes(2); - expect(profile).toEqual({name: "fakeServiceProfile", type: "zosmf", host: "fakeHostBase"}); - }); - it("Should throw an error if it cannot get the service profile", async() => { - const profileManagerSpy = jest.spyOn(imperative.CliProfileManager.prototype, "load").mockResolvedValueOnce({ profile: undefined } as any); - let error; - try { - await profileUtils.getDefaultProfile("zosmf", false); - } catch (err) { - error = err; - } - expect(error).toBeDefined(); - expect(profileManagerSpy).toHaveBeenCalledTimes(1); - expect(error.message).toContain("zosmf"); - }); - it("Should throw an error if it cannot get both profiles", async() => { - const profileManagerSpy = jest.spyOn(imperative.CliProfileManager.prototype, "load").mockResolvedValue({ profile: undefined } as any); - let error; - try { - await profileUtils.getDefaultProfile("zosmf", true); - } catch (err) { - error = err; - } - expect(error).toBeDefined(); - expect(profileManagerSpy).toHaveBeenCalledTimes(2); - expect(error.message).toContain("zosmf"); - expect(error.message).toContain("base"); - }); - }); -}); \ No newline at end of file diff --git a/packages/core/__tests__/utils/__integration__/__scripts__/create_profile.sh b/packages/core/__tests__/utils/__integration__/__scripts__/create_profile.sh deleted file mode 100755 index 2adf3a2c35..0000000000 --- a/packages/core/__tests__/utils/__integration__/__scripts__/create_profile.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e -type=$1 -name=$2 - -echo "================CREATE PROFILE===============" -# Can't use daemon because we need to override ZOWE_CLI_HOME -ZOWE_USE_DAEMON=false zowe profiles create $type $name $3 -if [ $? -gt 0 ] -then - exit $? -fi \ No newline at end of file diff --git a/packages/core/__tests__/utils/__integration__/__scripts__/delete_profile.sh b/packages/core/__tests__/utils/__integration__/__scripts__/delete_profile.sh deleted file mode 100755 index c6ad2a1ea6..0000000000 --- a/packages/core/__tests__/utils/__integration__/__scripts__/delete_profile.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e -type=$1 -name=$2 - -echo "================DELETE PROFILE===============" -# Can't use daemon because we need to override ZOWE_CLI_HOME -ZOWE_USE_DAEMON=false zowe profiles delete $type $name -if [ $? -gt 0 ] -then - exit $? -fi \ No newline at end of file diff --git a/packages/core/__tests__/utils/__unit__/CoreUtils.unit.test.ts b/packages/core/__tests__/utils/__unit__/CoreUtils.unit.test.ts index e238ee2df1..1ee588447d 100644 --- a/packages/core/__tests__/utils/__unit__/CoreUtils.unit.test.ts +++ b/packages/core/__tests__/utils/__unit__/CoreUtils.unit.test.ts @@ -9,6 +9,7 @@ * */ +/* eslint-disable deprecation/deprecation */ import * as CoreUtils from "../../../src/utils/CoreUtils"; jest.mock("fs"); diff --git a/packages/core/__tests__/utils/__unit__/ProfileUtils.unit.test.ts b/packages/core/__tests__/utils/__unit__/ProfileUtils.unit.test.ts deleted file mode 100644 index 49a3dce17e..0000000000 --- a/packages/core/__tests__/utils/__unit__/ProfileUtils.unit.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import * as ProfileUtils from "../../../src/utils/ProfileUtils"; -import { ImperativeConfig, EnvironmentalVariableSettings, CliProfileManager, ImperativeError } from "@zowe/imperative"; -import * as os from "os"; -import * as path from "path"; - -describe("ProfileUtils", () => { - afterEach(() => { - jest.restoreAllMocks(); - }); - - describe("getZoweDir", () => { - const expectedLoadedConfig = { - name: "zowe", - defaultHome: path.join("z", "zowe"), - envVariablePrefix: "ZOWE" - }; - let defaultHome: string; - - beforeEach(() => { - jest.spyOn(EnvironmentalVariableSettings, "read").mockReturnValue({ cliHome: { value: null } } as any); - ImperativeConfig.instance.loadedConfig = undefined as any; - jest.spyOn(os, "homedir").mockReturnValue(expectedLoadedConfig.defaultHome); - defaultHome = path.join(expectedLoadedConfig.defaultHome, ".zowe"); - }); - - it("should return the ENV cliHome even if loadedConfig is set in the process", () => { - jest.spyOn(EnvironmentalVariableSettings, "read").mockReturnValue({ cliHome: { value: "test" } } as any); - expect(ImperativeConfig.instance.loadedConfig).toBeUndefined(); - expect(ProfileUtils.getZoweDir()).toEqual("test"); - expect(ImperativeConfig.instance.loadedConfig).toEqual({ ...expectedLoadedConfig, defaultHome }); - }); - - it("should return the defaultHome and set loadedConfig if undefined", () => { - expect(ImperativeConfig.instance.loadedConfig).toBeUndefined(); - expect(ProfileUtils.getZoweDir()).toEqual(defaultHome); - expect(ImperativeConfig.instance.loadedConfig).toEqual({ ...expectedLoadedConfig, defaultHome }); - }); - - it("should return the defaultHome and reset loadedConfig if defaultHome changes", () => { - expect(ImperativeConfig.instance.loadedConfig).toBeUndefined(); - ImperativeConfig.instance.loadedConfig = { ...expectedLoadedConfig, defaultHome: "test" }; - expect(ImperativeConfig.instance.loadedConfig?.defaultHome).toEqual("test"); - expect(ProfileUtils.getZoweDir()).toEqual(defaultHome); - expect(ImperativeConfig.instance.loadedConfig).toEqual({ ...expectedLoadedConfig, defaultHome }); - }); - - it("should return the defaultHome without resetting loadedConfig", () => { - expect(ImperativeConfig.instance.loadedConfig).toBeUndefined(); - ImperativeConfig.instance.loadedConfig = expectedLoadedConfig; - expect(ProfileUtils.getZoweDir()).toEqual(defaultHome); - expect(ImperativeConfig.instance.loadedConfig).toEqual({ ...expectedLoadedConfig, defaultHome }); - }); - }); - - describe("getDefaultProfile", () => { - it("should throw an error if the CLIProfileManager fails to load a profile", async () => { - jest.spyOn(CliProfileManager.prototype, "load").mockRejectedValueOnce("failed to load a profile"); - let caughtError; - try { - await ProfileUtils.getDefaultProfile("test"); - } catch (err) { - caughtError = err; - } - - expect(caughtError).toBeInstanceOf(ImperativeError); - expect(caughtError.message).toContain("Failed to load default profile"); - }); - }); -}); diff --git a/packages/core/package.json b/packages/core/package.json index b14c644696..1526dd8d49 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/core-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "description": "Core libraries shared by Zowe SDK packages", "author": "Zowe", "license": "EPL-2.0", @@ -45,14 +45,17 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "comment-json": "4.1.1", - "string-width": "4.2.3" + "comment-json": "~4.2.3", + "string-width": "^4.2.3" }, "devDependencies": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/imperative": "5.27.1" + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" }, "peerDependencies": { - "@zowe/imperative": "^5.0.0" + "@zowe/imperative": "^8.0.0-next" + }, + "engines": { + "node": ">=18.12.0" } } diff --git a/packages/core/src/apiml/Services.ts b/packages/core/src/apiml/Services.ts index 64baef94b3..dc02266c61 100644 --- a/packages/core/src/apiml/Services.ts +++ b/packages/core/src/apiml/Services.ts @@ -40,7 +40,7 @@ export class Services { ); // Get the APIML configs from the loaded imperative config - for (const apimlConfig of (ImperativeConfig.instance.loadedConfig.apimlConnLookup || [])) { + for (const apimlConfig of ImperativeConfig.instance.loadedConfig.apimlConnLookup || []) { apimlConfigs.push({ ...apimlConfig, connProfType: apimlConfig.connProfType || ImperativeConfig.instance.loadedConfig.profiles[0].type, @@ -50,7 +50,7 @@ export class Services { // Load APIML configs from all plugins for (const pluginCfgProps of PluginManagementFacility.instance.allPluginCfgProps) { - for (const apimlConfig of (pluginCfgProps.impConfig.apimlConnLookup || [])) { + for (const apimlConfig of pluginCfgProps.impConfig.apimlConnLookup || []) { apimlConfigs.push({ ...apimlConfig, connProfType: apimlConfig.connProfType || pluginCfgProps.impConfig.profiles[0].type, @@ -125,7 +125,7 @@ export class Services { profInfo.pluginConfigs.add(config); profInfo.gatewayUrlConflicts[config.pluginName] = [ - ...(profInfo.gatewayUrlConflicts[config.pluginName] || []), + ...profInfo.gatewayUrlConflicts[config.pluginName] || [], apiInfo.gatewayUrl ]; } @@ -246,6 +246,9 @@ export class Services { conflictingPluginsList += ` // "${element}": "${profileInfo.gatewayUrlConflicts[element].join('", "')}"`; }); + + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + const basepathConflictMessage = ` // --- // Warning: basePath conflict detected! @@ -261,7 +264,7 @@ export class Services { ${_genCommentsHelper("basePath", basePaths)} "basePath": "${defaultBasePath}" }` - ); + ) as any; } }); @@ -287,7 +290,7 @@ export class Services { "${defaultKey}": "${trueDefault}"`; // Terminate the JSON string jsonString += '\n}'; - configDefaults = JSONC.parse(jsonString); + configDefaults = JSONC.parse(jsonString) as any; } } diff --git a/packages/core/src/constants/Core.constants.ts b/packages/core/src/constants/Core.constants.ts index 0d8d3a1f24..a463ee289a 100644 --- a/packages/core/src/constants/Core.constants.ts +++ b/packages/core/src/constants/Core.constants.ts @@ -381,33 +381,6 @@ export class ProfileConstants { } }, required: [] - }, - createProfileExamples: [ - { - options: "base1 --host example.com --port 443 --user admin --password 123456", - description: "Create a profile called 'base1' to connect to host example.com and port 443" - }, - { - options: "base2 --host example.com --user admin --password 123456 --reject-unauthorized false", - description: "Create a profile called 'base2' to connect to host example.com (default port - 443) " + - "and allow self-signed certificates" - }, - { - options: "base3 --host example.com --port 1443", - description: "Create a profile called 'base3' to connect to host example.com and port 1443, " + - " not specifying a username or password so they are not stored on disk; these will need to be specified on every command" - }, - { - options: "base4 --reject-unauthorized false", - description: "Create a zosmf profile called 'base4' to connect to default port 443 and allow self-signed certificates, " + - "not specifying a username, password, or host so they are not stored on disk; these will need to be specified on every command" - } - ], - updateProfileExamples: [ - { - options: "base1 --user newuser --password newp4ss", - description: "Update a base profile named 'base1' with a new username and password" - } - ] + } }; } diff --git a/packages/core/src/rest/ZosmfHeaders.ts b/packages/core/src/rest/ZosmfHeaders.ts index 1a7421ff46..ae4025174e 100644 --- a/packages/core/src/rest/ZosmfHeaders.ts +++ b/packages/core/src/rest/ZosmfHeaders.ts @@ -9,7 +9,7 @@ * */ -import { IHeaderContent } from "./doc/IHeaderContent"; +import { IHeaderContent } from "@zowe/imperative"; /** * Class to contain default z/OSMF headers diff --git a/packages/core/src/rest/ZosmfRestClient.ts b/packages/core/src/rest/ZosmfRestClient.ts index 0f64ffad7c..845d72ac63 100644 --- a/packages/core/src/rest/ZosmfRestClient.ts +++ b/packages/core/src/rest/ZosmfRestClient.ts @@ -10,7 +10,7 @@ */ import { - IImperativeError, Logger, NextVerFeatures, RestClient, TextUtils, + IImperativeError, Logger, RestClient, RestConstants, SessConstants } from "@zowe/imperative"; import { ZosmfHeaders } from "./ZosmfHeaders"; @@ -25,7 +25,7 @@ import { ZosmfHeaders } from "./ZosmfHeaders"; export class ZosmfRestClient extends RestClient { /** - * Use the Brightside logger instead of the imperative logger + * Use the Zowe logger instead of the imperative logger * @type {Logger} */ public get log(): Logger { @@ -54,11 +54,6 @@ export class ZosmfRestClient extends RestClient { * @memberof ZosmfRestClient */ protected processError(original: IImperativeError): IImperativeError { - // TODO:V3_ERR_FORMAT - Remove block in V3 - if (!NextVerFeatures.useV3ErrFormat()) { - original.msg = "z/OSMF REST API Error:\n" + original.msg; - } - let causeErrorsJson; let causeErrorsString = ""; if (original.causeErrors) { @@ -75,10 +70,8 @@ export class ZosmfRestClient extends RestClient { " Here is the full error before deleting the stack:\n%s", JSON.stringify(causeErrorsJson)); this.log.error("The stack has been deleted from the error before displaying the error to the user"); delete causeErrorsJson.stack; // remove the stack field + original.causeErrors = JSON.stringify(causeErrorsJson, null); } - - // if we didn't get an error, make the parsed causeErrorsString part of the error - causeErrorsString = TextUtils.prettyJson(causeErrorsJson, undefined, false); } } catch (e) { // if there's an error, the causeErrors text is not JSON @@ -86,76 +79,45 @@ export class ZosmfRestClient extends RestClient { } const origMsgFor401 = original.msg; - // TODO:V3_ERR_FORMAT - Don't test for env variable in V3 - if (NextVerFeatures.useV3ErrFormat()) { - // extract properties from causeErrors and place them into 'msg' as user-focused messages - if (causeErrorsJson?.details?.length > 0) { - for (const detail of causeErrorsJson.details) { - original.msg += "\n" + detail; - } + // extract properties from causeErrors and place them into 'msg' as user-focused messages + if (causeErrorsJson?.details?.length > 0) { + for (const detail of causeErrorsJson.details) { + original.msg += "\n" + detail; } - if (causeErrorsJson?.messages?.length > 0) { - for (const message of causeErrorsJson.messages) { - original.msg += "\n" + message.messageContent; - } + } + if (causeErrorsJson?.messages?.length > 0) { + for (const message of causeErrorsJson.messages) { + original.msg += "\n" + message.messageContent; } - } else { // TODO:V3_ERR_FORMAT - Remove in V3 - original.msg += "\n" + causeErrorsString; // add the data string which is the original error + } + if (causeErrorsJson?.message?.length > 0) { + original.msg += "\n" + causeErrorsJson.message; } // add further clarification on authentication errors if (this.response && this.response.statusCode === RestConstants.HTTP_STATUS_401) { - // TODO:V3_ERR_FORMAT - Don't test for env variable in V3 - if (NextVerFeatures.useV3ErrFormat()) { - if (!original.causeErrors || Object.keys(original.causeErrors ).length === 0) { - /* We have no causeErrors, so place the original msg we got for a 401 - * into the 'response from service' part of our error. - */ - original.causeErrors = `{"Error": "${origMsgFor401}"}`; - } - original.msg += "\nThis operation requires authentication."; + if (!original.causeErrors || Object.keys(original.causeErrors ).length === 0) { + /* We have no causeErrors, so place the original msg we got for a 401 + * into the 'response from service' part of our error. + */ + original.causeErrors = `{"Error": "${origMsgFor401}"}`; + } + original.msg += "\nThis operation requires authentication."; - if (this.session.ISession.type === SessConstants.AUTH_TYPE_BASIC) { - original.msg += "\nUsername or password are not valid or expired."; - } else if (this.session.ISession.type === SessConstants.AUTH_TYPE_TOKEN) { - if (this.session.ISession.tokenType === SessConstants.TOKEN_TYPE_APIML && !this.session.ISession.basePath) { - original.msg += `\nToken type "${SessConstants.TOKEN_TYPE_APIML}" requires base path to be defined.\n` + - "You must either connect with username and password or provide a base path."; - } else { - original.msg += "\nToken is not valid or expired.\n" + - "To obtain a new valid token, use the following command: `zowe config secure`\n" + - "For CLI usage, see `zowe config secure --help`"; - } - // TODO: Add PFX support in the future - } else if (this.session.ISession.type === SessConstants.AUTH_TYPE_CERT_PEM) { - original.msg += "\nCertificate is not valid or expired."; - } - } else { // TODO:V3_ERR_FORMAT - Remove in V3 - original.msg = "This operation requires authentication.\n\n" + original.msg + - "\nHost: " + this.session.ISession.hostname + - "\nPort: " + this.session.ISession.port + - "\nBase Path: " + this.session.ISession.basePath + - "\nResource: " + this.mResource + - "\nRequest: " + this.mRequest + - "\nHeaders: " + JSON.stringify(this.mReqHeaders) + - "\nPayload: " + this.mRequest + - "\n" - ; - if (this.session.ISession.type === SessConstants.AUTH_TYPE_BASIC) { - original.additionalDetails = "Username or password are not valid or expired.\n\n"; - } else if (this.session.ISession.type === SessConstants.AUTH_TYPE_TOKEN && this.session.ISession.tokenValue != null) { - if (this.session.ISession.tokenType === SessConstants.TOKEN_TYPE_APIML && !this.session.ISession.basePath) { - original.additionalDetails = `Token type "${SessConstants.TOKEN_TYPE_APIML}" requires base path to be defined.\n\n` + - "You must either connect with username and password or provide a base path."; - } else { - original.additionalDetails = "Token is not valid or expired.\n" + + if (this.session.ISession.type === SessConstants.AUTH_TYPE_BASIC) { + original.msg += "\nUsername or password are not valid or expired."; + } else if (this.session.ISession.type === SessConstants.AUTH_TYPE_TOKEN) { + if (this.session.ISession.tokenType === SessConstants.TOKEN_TYPE_APIML && !this.session.ISession.basePath) { + original.msg += `\nToken type "${SessConstants.TOKEN_TYPE_APIML}" requires base path to be defined.\n` + + "You must either connect with username and password or provide a base path."; + } else { + original.msg += "\nToken is not valid or expired.\n" + "To obtain a new valid token, use the following command: `zowe config secure`\n" + "For CLI usage, see `zowe config secure --help`"; - } - // TODO: Add PFX support in the future - } else if (this.session.ISession.type === SessConstants.AUTH_TYPE_CERT_PEM) { - original.additionalDetails = "Certificate is not valid or expired.\n\n"; } + // TODO: Add PFX support in the future + } else if (this.session.ISession.type === SessConstants.AUTH_TYPE_CERT_PEM) { + original.msg += "\nCertificate is not valid or expired."; } } diff --git a/packages/core/src/rest/doc/IHeaderContent.ts b/packages/core/src/rest/doc/IHeaderContent.ts index 776e788566..c71a8e9307 100644 --- a/packages/core/src/rest/doc/IHeaderContent.ts +++ b/packages/core/src/rest/doc/IHeaderContent.ts @@ -12,6 +12,7 @@ /** * Interface to add index signature to http headers * @export + * @deprecated - use Imperative's IHeaderContent instead * @interface IHeaderContent */ export interface IHeaderContent { diff --git a/packages/core/src/utils/CoreUtils.ts b/packages/core/src/utils/CoreUtils.ts index e6fd5555bf..a16aa7ca4b 100644 --- a/packages/core/src/utils/CoreUtils.ts +++ b/packages/core/src/utils/CoreUtils.ts @@ -20,6 +20,7 @@ const stringWidth = require("string-width"); * @param {string} str - string to add the padding to * @param {number} len - final length of the padded string * @param {string} [padChar=" "] - Padding character + * @deprecated - use string.padStart instead * @return {string} Padded string */ export function padLeft(str: string, len: number, padChar: string = " "): string { @@ -93,16 +94,16 @@ export function getErrorContext(content: string | string[], lineIndex: number): // Gather the line before in case we are able to get it if (lineIndex > 0) { - retValue += trimLineToTerminalWidth(`\n ${padLeft(lineIndex.toString(), maxLineIndexLength)} | ${lines[lineIndex - 1]}`); + retValue += trimLineToTerminalWidth(`\n ${lineIndex.toString().padStart(maxLineIndexLength)} | ${lines[lineIndex - 1]}`); } // Format the current line of the retValue += - trimLineToTerminalWidth(`\n > ${TextUtils.chalk.red(padLeft((lineIndex + 1).toString(), maxLineIndexLength))} | ${lines[lineIndex]}`); + trimLineToTerminalWidth(`\n > ${TextUtils.chalk.red((lineIndex + 1).toString().padStart(maxLineIndexLength))} | ${lines[lineIndex]}`); // Gather the next line in case we are able to get it if (lineIndex + 1 < lines.length) { - retValue += trimLineToTerminalWidth(`\n ${padLeft((lineIndex + 2).toString(), maxLineIndexLength)} | ${lines[lineIndex + 1]}`); + retValue += trimLineToTerminalWidth(`\n ${(lineIndex + 2).toString().padStart(maxLineIndexLength)} | ${lines[lineIndex + 1]}`); } return retValue; @@ -153,7 +154,7 @@ export function readStdin(): Promise { const stdinReadError: IImperativeError = { msg: "Error encountered while reading from stdin", causeErrors: error, - additionalDetails: (error == null) ? undefined : error.message + additionalDetails: error == null ? undefined : error.message }; reject(stdinReadError); }); diff --git a/packages/core/src/utils/ProfileUtils.ts b/packages/core/src/utils/ProfileUtils.ts deleted file mode 100644 index 027e6c0325..0000000000 --- a/packages/core/src/utils/ProfileUtils.ts +++ /dev/null @@ -1,109 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ImperativeConfig, IProfileLoaded, CliProfileManager, IProfile, Logger, ImperativeError } from "@zowe/imperative"; -import * as path from "path"; -import * as os from "os"; - -/** - * Retrieves the Zowe CLI home directory. In the situation Imperative has - * not initialized it we mock a default value. - * @returns {string} - Returns the Zowe home directory - */ -export function getZoweDir(): string { - const defaultHome = path.join(os.homedir(), ".zowe"); - if (ImperativeConfig.instance.loadedConfig?.defaultHome !== defaultHome) { - ImperativeConfig.instance.loadedConfig = { - name: "zowe", - defaultHome, - envVariablePrefix: "ZOWE" - }; - } - return ImperativeConfig.instance.cliHome; -} - -/** - * Loads default z/OSMF profile. The profile must have already been - * created using Zowe CLI, and not rely on base profiles - * - * @param {string} profileType - The name of the profile type - * @param {boolean} mergeWithBase - Whether or not to merge with the base profile - * @returns {IProfile} - The default profile (or merged profile, if requested) - */ -export async function getDefaultProfile(profileType: string, mergeWithBase?: boolean) { - - const profileRootDir: string = path.join(getZoweDir(), "profiles"); - const logger: Logger = Logger.getImperativeLogger(); - let profileManager: CliProfileManager; - let profileLoaded: IProfileLoaded; - - try { - // Create the profile manager - profileManager = new CliProfileManager({ - profileRootDirectory: profileRootDir, - type: profileType - }); - - // Load the profile using the profile manager - profileLoaded = await profileManager.load({ - loadDefault: true - }); - } catch (err) { - logger.warn(err.message); - } - - // Throw an error if there was no default profile found and no base profile requested - if ((!profileLoaded || !profileLoaded.profile) && !mergeWithBase) { - throw new ImperativeError({msg: `Failed to load default profile of type "${profileType}"`}); - } - - // Give the profile back as-is if the profile is not to be merged with the base profile - if (mergeWithBase === false) { - return profileLoaded.profile; - } - - let baseProfileManager: CliProfileManager; - let baseProfileLoaded: IProfileLoaded; - - try { - baseProfileManager = new CliProfileManager({ - profileRootDirectory: profileRootDir, - type: "base" - }); - - baseProfileLoaded = await baseProfileManager.load({ - loadDefault: true - }); - } catch (err) { - logger.warn(err.message); - } - - // Return service profile if there was no base profile found and service profile existed. - // Return base profile if there was no service profile found and base profile existed. - // If both exist, combine. Otherwise, error - if ((!baseProfileLoaded || !baseProfileLoaded.profile) && (profileLoaded && profileLoaded.profile)) { - return profileLoaded.profile; - } else if (baseProfileLoaded && baseProfileLoaded.profile && (!profileLoaded || !profileLoaded.profile)) { - return baseProfileLoaded.profile; - } else if ((!baseProfileLoaded || !baseProfileLoaded.profile) && (!profileLoaded || !profileLoaded.profile)) { - throw new ImperativeError({msg: `Failed to load default profiles of types "${profileType}" and "base"`}); - } - - const combinedProfile: IProfile = JSON.parse(JSON.stringify(baseProfileLoaded.profile)); - - for (const propertyName in profileLoaded.profile) { - if (profileLoaded.profile[propertyName] != null) { - combinedProfile[propertyName] = profileLoaded.profile[propertyName]; - } - } - - return combinedProfile; -} \ No newline at end of file diff --git a/packages/core/src/utils/index.ts b/packages/core/src/utils/index.ts index 0da3c75968..a3f1390ef9 100644 --- a/packages/core/src/utils/index.ts +++ b/packages/core/src/utils/index.ts @@ -11,4 +11,3 @@ export * from "./CoreUtils"; export * from "./CommonConstants"; -export * from "./ProfileUtils"; diff --git a/packages/core/typedoc.json b/packages/core/typedoc.json index 2b97359f2c..b15f87adc5 100644 --- a/packages/core/typedoc.json +++ b/packages/core/typedoc.json @@ -1,5 +1,6 @@ { "out": "./docs/typedoc/", - "exclude": "**/__tests__/**", + "exclude": ["**/__tests__/**"], + "entryPoints": ["src/index.ts"], "cleanOutputDir": true } \ No newline at end of file diff --git a/packages/imperative/.eslintrc.js b/packages/imperative/.eslintrc.js index 01fe3c5774..fa630b127c 100644 --- a/packages/imperative/.eslintrc.js +++ b/packages/imperative/.eslintrc.js @@ -5,7 +5,8 @@ module.exports = { "sourceType": "module", "project": [ "./tsconfig.json", - "./__tests__/tsconfig.json" + "./__tests__/tsconfig.json", + "./tsconfig-tests.json" ] } } \ No newline at end of file diff --git a/packages/imperative/CHANGELOG.md b/packages/imperative/CHANGELOG.md index aa279e6274..0889c0125a 100644 --- a/packages/imperative/CHANGELOG.md +++ b/packages/imperative/CHANGELOG.md @@ -2,6 +2,482 @@ All notable changes to the Imperative package will be documented in this file. +## Recent Changes + +- Update: Final prerelease +- Update: See `5.27.1` for details + +## `8.0.0-next.202408301809` + +- LTS Breaking: Removed the following obsolete V1 profile classes/functions: + - `CliProfileManager` + - `CliUtils.getOptValueFromProfiles` + - `CommandProfiles` + - `ProfileValidator` + + See [`8.0.0-next.202408271330`](#800-next202408271330) for replacements +- Next Breaking: Changed 2nd parameter of `CliUtils.getOptValuesFromConfig` method from type `ICommandDefinition` to `ICommandProfile`. +- Next Breaking: Renamed `ConfigSecure.secureFieldsForLayer` method to `securePropsForLayer`. + +## `8.0.0-next.202408291544` + +- Enhancement: Added a new SDK method (`ConfigSecure.secureFieldsForLayer`) to allow developers to get vault content in the context of the specified layer. [#2206](https://github.com/zowe/zowe-cli/issues/2206) +- Enhancement: Added a new SDK method (`ProfileInfo.secureFieldsWithDetails`) to allow developers to the more details regarding the securely stored properties. [#2206](https://github.com/zowe/zowe-cli/issues/2206) + +## `8.0.0-next.202408271330` + +- LTS Breaking: [#2231](https://github.com/zowe/zowe-cli/issues/2231) + - Removed the obsolete V1 `profiles` property from `IHandlerParameters` interface - Use `IHandlerParameters.arguments` to access profile properties in a command handler + - Deprecated the following obsolete V1 profile interfaces: + - `IProfileTypeConfiguration.dependencies` - For team config, use nested profiles instead + - `IProfileTypeConfiguration.validationPlanModule` - For team config, validate with JSON schema instead + - Deprecated the following obsolete V1 profile classes/functions: + - `CliProfileManager` - Use `ProfileInfo` class to manage team config profiles + - `CliUtils.getOptValueFromProfiles` - Use `CliUtils.getOptValuesFromConfig` to load properties from team config + - `CommandProfiles` - Use `ImperativeConfig.instance.config.api.profiles` to load profiles from team config + - `ProfileValidator` - No direct replacement + +## `8.0.0-next.202408231832` + +- LTS Breaking: Fixed command parsing error where `string` typed options would be converted into `number`s if the value provided by the user consists only of numeric characters. [#1881](https://github.com/zowe/zowe-cli/issues/1881) +- LTS Breaking: Renamed `Proxy` class to `ProxySettings` to avoid name conflict with JS built-in `Proxy` object. [#2230](https://github.com/zowe/zowe-cli/issues/2230) + +## `8.0.0-next.202408191401` + +- Update: See `5.26.3` and `5.27.0` for details + +## `8.0.0-next.202408131445` + +- Update: See `5.26.2` for details + +## `8.0.0-next.202408092029` + +- BugFix: Resolved bug that resulted in user not being prompted for a key passphrase if it is located in the secure credential array of the ssh profile. [#1770](https://github.com/zowe/zowe-cli/issues/1770) + +## `8.0.0-next.202407262216` + +- Update: See `5.26.1` for details + +## `8.0.0-next.202407232256` + +- Enhancement: Allowed boolean value (`false`) to be provided to the Credential Manager related function. [zowe-explorer-vscode#2622](https://github.com/zowe/zowe-explorer-vscode/issues/2622) +- Update: See `5.26.0` for details + +## `8.0.0-next.202407181904` + +- Enhancement: Added the function ConfigUtils.formGlobOrProjProfileNm and modified the function ConfigBuilder.build so that the 'zowe config init' command now generates a base profile name of 'global_base' or 'project_base', depending on whether a global or project configuration file is being generated. Related to Zowe Explorer issue https://github.com/zowe/zowe-explorer-vscode/issues/2682. + +## `8.0.0-next.202407181255` + +- BugFix: Resolved bug that resulted in each plug-in to have identical public registries regardless of actual installation location/reference. [#2189](https://github.com/zowe/zowe-cli/pull/2189) +- BugFix: Resolved bug that resulted in every plug-in to have the same registry location field as the first if multiple plugins were installed in the same command. [#2189](https://github.com/zowe/zowe-cli/pull/2189) + +## `8.0.0-next.202407112150` + +- Enhancement: Add client-side custom-event handling capabilities. [#2136](https://github.com/zowe/zowe-cli/pull/2136) +- Next-Breaking: Refactored the Imperative Event Emitter class. [#2136](https://github.com/zowe/zowe-cli/pull/2136) + - Removed the `ImperativeEventEmitter` class. + - Added an `EventProcessor` class to handle event listening and emitting. + - Added an `EventOperator` class to handle creation and deletion of `EventProcessors`. + - Added an `EventUtils` class to contain all common utility methods for the Client Event Handling capabilities. + - Added `IEmitter`, `IWatcher`, and `IEmitterAndWatcher` interfaces to expose what application developers should see. + +## `8.0.0-next.202407051717` + +- BugFix: V3 Breaking: Modified the ConvertV1Profiles.convert API to accept a new ProfileInfo option and initialize components sufficiently to enable VSCode apps to convert V1 profiles. [#2170](https://github.com/zowe/zowe-cli/issues/2170) + +## `8.0.0-next.202407021516` + +- BugFix: Updated dependencies for technical currency [#2188](https://github.com/zowe/zowe-cli/pull/2188) +- Update: See `5.25.0` for details + +## `8.0.0-next.202406201950` + +- Enhancement: Added `ProfileInfo.profileManagerWillLoad` function to verify the credential manager can load. [#2111](https://github.com/zowe/zowe-cli/issues/2111) + +## `8.0.0-next.202406111958` + +- LTS Breaking: Modified the @zowe/imperative SDK [#2083](https://github.com/zowe/zowe-cli/issues/2083) + - Removed the following exported classes: + - AbstractAuthHandler + - AbstractCommandYargs + - AbstractHelpGenerator + - AbstractHelpGeneratorFactory + - CommandPreparer + - CommandProcessor + - CommandUtils + - CommandYargs + - CompressionUtils + - ConfigAutoStore + - ConfigurationLoader + - ConfigurationValidator + - DefinitionTreeResolver + - FailedCommandHandler + - GroupCommandYargs + - HelpConstants + - HelpGeneratorFactory + - ImperativeReject + - LoggerConfigBuilder + - LoggerUtils + - RestStandAloneUtils + - SharedOptions + - SyntaxValidator + - WebHelpManager + - YargsConfigurer + - YargsDefiner + - Removed the following exported interfaces: + - ICommandHandlerResponseChecker + - ICommandHandlerResponseValidator + - ICommandValidatorError + - ICommandValidatorResponse + - IConstructor + - IHelpGenerator + - IHelpGeneratorFactory + - IYargsParms + - IYargsResponse + - Deprecated the following classes: + - Operation + - Operations + +## `8.0.0-next.202406111728` + +- Enhancement: Added `BufferBuilder` utility class to provide convenient way of downloading to a stream that can be read as a buffer. [#2167](https://github.com/zowe/zowe-cli/pull/2167) +- BugFix: Fixed error in REST client that when using stream could cause small data sets to download with incomplete contents. [#744](https://github.com/zowe/zowe-cli/issues/744) +- BugFix: Updated `micromatch` dependency for technical currency. [#2167](https://github.com/zowe/zowe-cli/pull/2167) + +## `8.0.0-next.202406061600` + +- BugFix: Updated `braces` dependency for technical currency. [#2158](https://github.com/zowe/zowe-cli/pull/2158) + +## `8.0.0-next.202405241520` + +- BugFix: Modified command output to show appropriate error message given available ImperativeError properties. [#1897](https://github.com/zowe/zowe-cli/issues/1897) +- Patch: Modify error text in SyntaxValidator.invalidOptionError. [#2138](https://github.com/zowe/zowe-cli/issues/2138) + +## `8.0.0-next.202405211929` + +- BugFix: Fixed error "Only one instance of the Imperative Event Emitter is allowed" when running system tests. [#2146](https://github.com/zowe/zowe-cli/issues/2146) + +## `8.0.0-next.202405151329` + +- Enhancement: Add client-side event handling capabilities. [#1987](https://github.com/zowe/zowe-cli/issues/1987) + +## `8.0.0-next.202405061946` + +- Enhancement: Consolidated the Zowe client log files into the same directory. [#2116](https://github.com/zowe/zowe-cli/issues/2116) +- Deprecated: The `IO.FILE_DELIM` constant. Use `path.posix.sep` instead or `path.sep` for better cross-platform support. +- Deprecated: The `LoggerConfigBuilder.DEFAULT_LOG_DIR` and `LoggerConfigBuilder.DEFAULT_LOG_FILE_DIR` constants. Use `LoggerConfigBuilder.DEFAULT_LOGS_DIR` instead. + +## `8.0.0-next.202405031808` + +- BugFix: Restore the previous precedence of token over password in AbstractRestClient [#2109](https://github.com/zowe/zowe-cli/issues/2109) + +## `8.0.0-next.202404301428` + +- Enhancement: Add informative messages before prompting for connection property values in the CLI callback function getValuesBack. + +## `8.0.0-next.202404191414` + +- Enhancement: Added a new class named ConvertV1Profiles to enable other apps to better convert V1 profiles into a current Zowe config file. + - Refactored logic from convert-profiles.handler and ConfigBuilder.convert into ConvertV1Profiles.convert. + - Removed ConfigBuilder.convert. + - Replaced IConfigConvertResult with IConvertV1Profiles (which contains IConvertV1ProfResult). + - Renamed class V1ProfileConversion (formerly known as ProfileIO) to V1ProfileRead for consistency. + - Marked class V1ProfileRead as @internal. + +## `8.0.0-next.202403272026` + +- BugFix: Resolved technical currency by updating `markdown-it` dependency. [#2107](https://github.com/zowe/zowe-cli/pull/2107) + +## `8.0.0-next.202403251613` + +- BugFix: Fixed issue where the `ProfileInfo.addProfileTypeToSchema` function did not update the global schema if a project-level configuration was detected. [#2086](https://github.com/zowe/zowe-cli/issues/2086) +- BugFix: Updated debugging output for technical currency. [#2100](https://github.com/zowe/zowe-cli/pull/2100) + +## `8.0.0-next.202403141949` +- LTS Breaking: Modified the @zowe/imperative SDK [#1703](https://github.com/zowe/zowe-cli/issues/1703) + - Renamed class ProfileIO to V1ProfileConversion. + - Removed the following obsolete V1 profile functions: + - createProfileDirs + - deleteProfile + - exists + - writeMetaFile + - writeProfile + - Removed the following obsolete V1 profile constant: + - MAX_YAML_DEPTH + - Changed fileToProfileName from public to private + - Removed deprecated function ConfigProfiles.expandPath + - Use ConfigProfiles.getProfilePathFromName + - Removed deprecated function ProcessUtils.execAndCheckOutput + - Use ExecUtils.spawnAndGetOutput + +## `8.0.0-next.202403132009` + +- Enhancement: Prompt for user/password on SSH commands when a token is stored in the config. [#2081](https://github.com/zowe/zowe-cli/pull/2081) + +## `8.0.0-next.202403061549` + +- V3 Breaking: Changed prompting logic to prompt for port if port provided is 0 [#2075](https://github.com/zowe/zowe-cli/issues/2075) +- BugFix: Fixed issue with peerDep warnings showing when a plug-in is installed and the version ranges satisfy the semver requirements. [#2067](https://github.com/zowe/zowe-cli/pull/2067) + +## `8.0.0-next.202403041352` + +- BugFix: Updated engine to Node 18.12.0. [#2074](https://github.com/zowe/zowe-cli/pull/2074) +- BugFix: Removed `profileVersion` from the response given by `--show-inputs-only` to fix [#1689](https://github.com/zowe/zowe-cli/issues/1689). Extended that change to the `config report-env` command, where similar soon-to-be obsolete v1 considerations occur. +- BugFix: Changed text displayed for configuration from "V2" to "TeamConfig" [#2019](https://github.com/zowe/zowe-cli/issues/2019) +- BugFix: Eliminated a Node Version Manager (NVM) GUI popup dialog which NVM now displays during the `zowe config report-env` command by removing the NVM version number from our report. +- Enhancement: Replaced the term "Team configuration" with "Zowe client configuration" in the `zowe config report-env` command. + +- LTS Breaking: [#1703](https://github.com/zowe/zowe-cli/issues/1703) + - Removed the following obsolete V1 profile interfaces: + - @zowe/cli-test-utils + - ISetupEnvironmentParms.createOldProfiles + + - @zowe/imperative + - ICliLoadProfile + - ICliLoadAllProfiles + - ICommandLoadProfile + - ICommandProfileTypeConfiguration.createProfileExamples + - ICommandProfileTypeConfiguration.createProfileFromArgumentsHandler + - ICommandProfileTypeConfiguration.updateProfileExamples + - ICommandProfileTypeConfiguration.updateProfileFromArgumentsHandler + - IDeleteProfile + - ILoadAllProfiles + - ILoadProfile + - IProfileDeleted + - IProfileManager.loadCounter + - IProfileManagerFactory + - IProfileSaved + - IProfileValidated + - ISaveProfile + - ISaveProfileFromCliArgs + - ISetDefaultProfile + - IUpdateProfile + - IUpdateProfileFromCliArgs + - IValidateProfile + - IValidateProfileForCLI + - IValidateProfileWithSchema + + - Removed the following obsolete V1 profile classes/functions: + - @zowe/core-for-zowe-sdk + - File ProfileUtils.ts, which includes these functions: + - getDefaultProfile + - getZoweDir - moved to ProfileInfo.getZoweDir + + - @zowe/cli-test-utils + - TempTestProfiles.forceOldProfiles + - TestUtils.stripProfileDeprecationMessages + + - @zowe/imperative + - AbstractProfileManager + - Any remaining functions consolidated into CliProfileManager + - AbstractProfileManagerFactory + - BasicProfileManager + - Any remaining functions consolidated into CliProfileManager + - BasicProfileManagerFactory + - CliProfileManager + - clearDefault + - configurations + - constructFullProfilePath + - delete + - deleteProfile + - deleteProfileFromDisk + - getAllProfileNames + - getDefaultProfileName + - isProfileEmpty + - load + - loadAll + - loadCounter + - loadDependencies + - loadFailed + - loadProfile + - loadSpecificProfile + - locateExistingProfile + - managerParameters + - mergeProfiles + - META_FILE_SUFFIX + - PROFILE_EXTENSION + - profileRootDirectory + - profileTypeSchema + - save + - saveProfile + - setDefault + - update + - updateProfile + - validate + - validateProfile + - validateProfileAgainstSchema + - validateProfileObject + - validateRequiredDependenciesAreSpecified + - CommandProfiles + - getMeta + - getAll + - ImperativeProfileManagerFactory + - ProfileInfo.usingTeamConfig + - To detect if a team config exists, use ProfileInfo.getTeamConfig().exists + - To detect if only V1 profiles exist, use ProfileInfo.onlyV1ProfilesExist + + - @zowe/zos-uss-for-zowe-sdk + - SshBaseHandler + - Removed the unused, protected property ‘mSshProfile’ + + - Removed the following obsolete V1 profile constants: + - @zowe/imperative + - CoreMessages class + - createProfileCommandSummary + - createProfileDisableDefaultsDesc + - createProfileOptionDesc + - createProfileOptionOverwriteDesc + - createProfilesCommandDesc + - createProfilesCommandSummary + - deleteProfileActionDesc + - deleteProfileCommandDesc + - deleteProfileDepsDesc + - deleteProfileExample + - deleteProfileForceOptionDesc + - deleteProfileNameDesc + - deleteProfilesCommandDesc + - deleteProfilesCommandSummary + - detailProfileCommandDesc + - listGroupWithOnlyProfileCommandSummary + - listGroupWithOnlyProfileDefaultDesc + - listGroupWithOnlyProfilesDefinition + - listGroupWithOnlyProfileSetDesc + - listGroupWithOnlyProfilesSummary + - listProfileCommandDesc + - listProfileCommandSummary + - listProfileExample + - listProfileExampleShowContents + - listProfileLoadedModulesOptionDesc + - listProfilesFoundMessage + - listProfilesNotFoundMessage + - listProfileVerboseOptionDesc + - locateProfilesDesc + - overroteProfileMessage + - profileCreatedSuccessfully + - profileCreatedSuccessfullyAndPath + - profileCreateErrorDetails + - profileCreateErrorHeader + - profileDeletedSuccessfully + - profileDeleteErrorDetails + - profileDeleteErrorHeader + - profileDesc + - profileLoadError + - profileNotDeletedMessage + - profileReviewMessage + - profileUpdatedSuccessfullyAndPath + - selectProfileNameDesc + - setGroupWithOnlyProfilesCommandDesc + - setGroupWithOnlyProfilesListDesc + - setGroupWithOnlyProfilesSummary + - setProfileActionDesc + - setProfileActionSummary + - setProfileExample + - setProfileOptionDesc + - showDependenciesCommandDesc + - unableToCreateProfile + - unableToDeleteProfile + - unableToFindProfile + - unableToLoadRequestedProfilesError + - unexpectedProfileCreationError + - unexpectedProfileLoadError + - unexpectedProfilesLoadError + - unexpectedProfileUpdateError + - updateProfileActionDesc + - updateProfileCommandDesc + - updateProfileCommandSummary + - validateProfileCommandDesc + - validateProfileCommandSummary + - validateProfileGroupDesc + - validateProfileNameDesc + - validateProfileOptionDesc + - ProfilesConstants class + - DEPRECATE_TO_CONFIG_EDIT + - DEPRECATE_TO_CONFIG_INIT + - DEPRECATE_TO_CONFIG_LIST + - DEPRECATE_TO_CONFIG_SET + - PROFILES_COMMAND_TYPE_KEY + + - Annotated the following items as @internal: + - @zowe/imperative + - CommandProfileLoader + - ImperativeApi.profileManager + - ProfileValidator + +## `8.0.0-next.202402271901` + +- BugFix: Fixed chalk functionality that was broken due to the use of the removed `.enabled` property. [#2071](https://github.com/zowe/zowe-cli/issues/2071) + +## `8.0.0-next.202402261705` + +- LTS Breaking: Updated `ICommandArguments` and `IHandlerParameters` to accept strings or numbers per Yargs changes. [#2069](https://github.com/zowe/zowe-cli/pull/2069) +- BugFix: Correct the examples displayed by the `--help-examples` command. [#1865](https://github.com/zowe/zowe-cli/issues/1865) and [#1715](https://github.com/zowe/zowe-cli/issues/1715) +- BugFix: Updated additional dependencies for technical currency. [#2061](https://github.com/zowe/zowe-cli/pull/2061) +- BugFix: Updated engine to Node 16.7.0. [#2061](https://github.com/zowe/zowe-cli/pull/2061) + +## `8.0.0-next.202402221834` + +- Enhancement: Added multiple APIs to the `ProfileInfo` class to help manage schemas between client applications. [#2012](https://github.com/zowe/zowe-cli/issues/2012) + +## `8.0.0-next.202402211923` + +- BugFix: Updated dependencies for technical currency. [#2057](https://github.com/zowe/zowe-cli/pull/2057) + +## `8.0.0-next.202402132108` + +- LTS Breaking: Added Zowe release version output for `--version` [#2028](https://github.com/zowe/zowe-cli/issues/2028) +- Enhancement: Added `name-only` alias to `root` on `config list` command [#1797](https://github.com/zowe/zowe-cli/issues/1797) +- BugFix: Resolved technical currency by updating `socks` transitive dependency + + +## `8.0.0-next.202401191954` + +- LTS Breaking: Removed the following: + - All 'profiles' commands, since they only worked with now-obsolete V1 profiles. + - BasicProfileManager.initialize function + - These interfaces: + - IProfileManagerInit + - IProfileInitialized + +## `8.0.0-next.202401081937` + +- BugFix: Fixed error message shown for null option definition to include details about which command caused the error. [#2002](https://github.com/zowe/zowe-cli/issues/2002) + +## `8.0.0-next.202401031939` + +- Enhancement: Revised help text for consistency [#1756](https://github.com/zowe/zowe-cli/issues/1756) + +## `8.0.0-next.202311291643` + +- LTS Breaking: Removed check for `ZOWE_EDITOR` environment variable in `ProcessUtils.openInEditor` [#1867](https://github.com/zowe/zowe-cli/issues/1867) + +## `8.0.0-next.202311282012` + +- LTS Breaking: Unpinned dependency versions to allow for patch/minor version updates for dependencies [#1968](https://github.com/zowe/zowe-cli/issues/1968) + +## `8.0.0-next.202311141903` + +- LTS Breaking: Removed the following previously deprecated items: + - `flattenCommandTreeWithAliases()` -- Use `CommandUtils.flattenCommandTree()` instead + - `AbstractAuthHandler.getPromptParams()` -- Use `getAuthHandlerApi()` instead + - `BaseAuthHandler.getPromptParams()` -- Use `getAuthHandlerApi()` instead + - `promptForInput()` -- Use the asynchronous method `readPrompt()` instead + - `promptWithTimeout()` -- Use `readPrompt` instead which supports more options + - `Imperative.envVariablePrefix` -- Use `ImperativeConfig.instance.envVariablePrefix` instead + - `pluginHealthCheck()` -- Plugins that want to perform a health check can + specify the `pluginLifeCycle` property to load a class from the plugin. + The plugin can implement the `postInstall()` function of that class to perform + a health check, or any other desired operation. + - `IProfOpts.requireKeytar` -- removing the default implementation of `require("keytar")` from the caller app's node_modules folders + +## `8.0.0-next.202311141517` + +- LTS Breaking: Replaced the previously deprecated function AbstractCommandYargs.getBrightYargsResponse - use AbstractCommandYargs.getZoweYargsResponse + +## `8.0.0-next.202311132045` + +- Major: First major version bump for V3 + ## `5.27.1` - BugFix: Updated `dataobject-parser` dependency for technical currency. [#2262](https://github.com/zowe/zowe-cli/pull/2262) diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/Cmd.cli.auth.fruit.integration.test.ts b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/Cmd.cli.auth.fruit.integration.subtest.ts similarity index 64% rename from packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/Cmd.cli.auth.fruit.integration.test.ts rename to packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/Cmd.cli.auth.fruit.integration.subtest.ts index f8fed6e38f..059acf1bd7 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/Cmd.cli.auth.fruit.integration.test.ts +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/Cmd.cli.auth.fruit.integration.subtest.ts @@ -9,5 +9,7 @@ * */ -require("./Cmd.cli.auth.login.fruit.integration.subtest"); -require("./Cmd.cli.auth.logout.fruit.integration.subtest"); +describe("Cmd CLI Secure Tests", () => { + require("./Cmd.cli.auth.login.fruit.integration.subtest"); + require("./Cmd.cli.auth.logout.fruit.integration.subtest"); +}); \ No newline at end of file diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/Cmd.cli.auth.login.fruit.integration.subtest.ts b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/Cmd.cli.auth.login.fruit.integration.subtest.ts index 34f96c7cd4..c6c0a3def1 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/Cmd.cli.auth.login.fruit.integration.subtest.ts +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/Cmd.cli.auth.login.fruit.integration.subtest.ts @@ -12,14 +12,13 @@ import { runCliScript } from "../../../../../../src/TestUtil"; import { ITestEnvironment } from "../../../../../../__src__/environment/doc/response/ITestEnvironment"; import { SetupTestEnvironment } from "../../../../../../__src__/environment/SetupTestEnvironment"; -import { join } from "path"; -const fakeCertPath = join(__dirname, "__resources__", "fakeCert.cert"); -const fakeCertKeyPath = join(__dirname, "__resources__", "fakeKey.key"); +const fakeCertPath = "./fakeCert.cert"; +const fakeCertKeyPath = "./fakeKey.key"; // Test Environment populated in the beforeAll(); let TEST_ENVIRONMENT: ITestEnvironment; -describe("cmd-cli auth login", () => { +describe("imperative-test-cli auth login", () => { // Create the unique test environment beforeAll(async () => { TEST_ENVIRONMENT = await SetupTestEnvironment.createTestEnv({ @@ -28,222 +27,199 @@ describe("cmd-cli auth login", () => { }); }); - afterEach(() => { - // delete profiles between tests so that they can be recreated - require("rimraf").sync(join(TEST_ENVIRONMENT.workingDir, "profiles")); - }); - it("should load values from base profile and store token in it with alias", () => { - const response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_li.sh", - TEST_ENVIRONMENT.workingDir, ["fakeUser", "fakePass"]); - expect(response.stderr.toString()).toContain("command 'profiles create base-profile' is deprecated"); - expect(response.status).toBe(0); + const response = runCliScript(__dirname + "/__scripts__/auth_li_config_password.sh", + TEST_ENVIRONMENT.workingDir); // the output of the command should include token value - expect(response.stdout.toString()).toContain("user: fakeUser"); - expect(response.stdout.toString()).toContain("password: fakePass"); + expect(response.stderr.toString()).toBe(""); + expect(response.stdout.toString()).toContain("user: fakeUser"); + expect(response.stdout.toString()).toContain("password: fakePass"); expect(response.stdout.toString()).toContain("tokenType: jwtToken"); - expect(response.stdout.toString()).toContain("tokenValue: fakeUser:fakePass@fakeToken"); + expect(response.stdout.toString()).toContain("tokenValue: (secure value)"); + expect(response.status).toBe(0); }); it("should load values from base profile and store token in it - basic auth", () => { - const response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login.sh", - TEST_ENVIRONMENT.workingDir, ["fakeUser", "fakePass"]); - expect(response.stderr.toString()).toContain("command 'profiles create base-profile' is deprecated"); - expect(response.status).toBe(0); + const response = runCliScript(__dirname + "/__scripts__/auth_login_config_password.sh", + TEST_ENVIRONMENT.workingDir); // the output of the command should include token value - expect(response.stdout.toString()).toContain("user: fakeUser"); - expect(response.stdout.toString()).toContain("password: fakePass"); + expect(response.stderr.toString()).toBe(""); + expect(response.stdout.toString()).toContain("user: fakeUser"); + expect(response.stdout.toString()).toContain("password: fakePass"); expect(response.stdout.toString()).toContain("tokenType: jwtToken"); - expect(response.stdout.toString()).toContain("tokenValue: fakeUser:fakePass@fakeToken"); + expect(response.stdout.toString()).toContain("tokenValue: (secure value)"); + expect(response.status).toBe(0); }); it("should load values from base profile and store token in it - certificate auth", () => { - const response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_cert.sh", - TEST_ENVIRONMENT.workingDir, [fakeCertPath, fakeCertKeyPath]); - expect(response.stderr.toString()).toContain("command 'profiles create base-profile' is deprecated"); - expect(response.status).toBe(0); + const response = runCliScript(__dirname + "/__scripts__/auth_login_config_cert.sh", + TEST_ENVIRONMENT.workingDir); // the output of the command should include token value + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("certFile: " + fakeCertPath); expect(response.stdout.toString()).toContain("certKeyFile: " + fakeCertKeyPath); expect(response.stdout.toString()).toContain("tokenType: jwtToken"); - expect(response.stdout.toString()).toContain("tokenValue: fakeCertificate@fakeToken"); + expect(response.stdout.toString()).toContain("tokenValue: (secure value)"); + expect(response.status).toBe(0); }); it("should load values from base profile and show token only - basic auth", () => { - let response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_show_token.sh", - TEST_ENVIRONMENT.workingDir, ["fakeUser", "fakePass"]); - expect(response.stderr.toString()).toContain("command 'profiles create base-profile' is deprecated"); - expect(response.status).toBe(0); - - // the output of the command should include token value - expect(response.stdout.toString()).toContain("fakeUser:fakePass@fakeToken"); - - response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_show_profiles.sh", TEST_ENVIRONMENT.workingDir); + const response = runCliScript(__dirname + "/__scripts__/auth_login_config_password_show_token.sh", + TEST_ENVIRONMENT.workingDir); // the output of the command should not include token value - expect(response.stderr.toString()).toContain("command 'profiles list base-profiles' is deprecated"); - expect(response.status).toBe(0); + expect(response.stderr.toString()).toBe(""); + expect(response.stdout.toString()).toContain("Received a token of type = jwtToken"); + expect(response.stdout.toString()).toContain("The following token was retrieved and will not be stored in your profile:"); + expect(response.stdout.toString()).toContain("fakeUser:fakePass@fakeToken"); expect(response.stdout.toString()).not.toContain("tokenType:"); expect(response.stdout.toString()).not.toContain("tokenValue:"); + expect(response.status).toBe(0); }); it("should load values from base profile and show token only - certificate auth", () => { - let response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_show_token_cert.sh", - TEST_ENVIRONMENT.workingDir, [fakeCertPath, fakeCertKeyPath]); - expect(response.stderr.toString()).toContain("command 'profiles create base-profile' is deprecated"); - expect(response.status).toBe(0); - - // the output of the command should include token value - expect(response.stdout.toString()).toContain("fakeCertificate@fakeToken"); - - response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_show_profiles.sh", TEST_ENVIRONMENT.workingDir); + const response = runCliScript(__dirname + "/__scripts__/auth_login_config_cert_show_token.sh", + TEST_ENVIRONMENT.workingDir); // the output of the command should not include token value - expect(response.stderr.toString()).toContain("command 'profiles list base-profiles' is deprecated"); - expect(response.status).toBe(0); + expect(response.stderr.toString()).toBe(""); + expect(response.stdout.toString()).toContain("Received a token of type = jwtToken"); + expect(response.stdout.toString()).toContain("The following token was retrieved and will not be stored in your profile:"); + expect(response.stdout.toString()).toContain("fakeCertificate@fakeToken"); expect(response.stdout.toString()).not.toContain("tokenType:"); expect(response.stdout.toString()).not.toContain("tokenValue:"); + expect(response.status).toBe(0); }); it("should load values from base profile and show token in rfj - basic auth", () => { - let response = runCliScript(__dirname + "/__scripts__/base_profile_create.sh", - TEST_ENVIRONMENT.workingDir, ["fakeUser", "fakePass"]); - expect(response.stderr.toString()).toContain("command 'profiles create base-profile' is deprecated"); - expect(response.status).toBe(0); - // the output of the command should include token value - response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_show_token_rfj.sh", + let response = runCliScript(__dirname + "/__scripts__/auth_login_config_password_show_token_rfj.sh", TEST_ENVIRONMENT.workingDir); expect(response.stderr.toString()).toBe(""); - expect(response.status).toBe(0); expect(JSON.parse(response.stdout.toString()).data).toMatchObject({tokenType: "jwtToken", tokenValue: "fakeUser:fakePass@fakeToken"}); + expect(response.status).toBe(0); // the output of the command should not include token value - response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_show_profiles.sh", TEST_ENVIRONMENT.workingDir); - expect(response.stderr.toString()).toContain("command 'profiles list base-profiles' is deprecated"); - expect(response.status).toBe(0); + response = runCliScript(__dirname + "/__scripts__/show_profiles.sh", TEST_ENVIRONMENT.workingDir); + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).not.toContain("tokenType:"); expect(response.stdout.toString()).not.toContain("tokenValue:"); + expect(response.status).toBe(0); }); it("should load values from base profile and show token in rfj - certificate auth", () => { - let response = runCliScript(__dirname + "/__scripts__/base_profile_create_cert.sh", - TEST_ENVIRONMENT.workingDir, [fakeCertPath, fakeCertKeyPath]); - expect(response.stderr.toString()).toContain("command 'profiles create base-profile' is deprecated"); - expect(response.status).toBe(0); - // the output of the command should include token value - response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_show_token_rfj.sh", + let response = runCliScript(__dirname + "/__scripts__/auth_login_config_cert_show_token_rfj.sh", TEST_ENVIRONMENT.workingDir); expect(response.stderr.toString()).toBe(""); - expect(response.status).toBe(0); expect(JSON.parse(response.stdout.toString()).data).toMatchObject({tokenType: "jwtToken", tokenValue: "fakeCertificate@fakeToken"}); + expect(response.status).toBe(0); // the output of the command should not include token value - response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_show_profiles.sh", TEST_ENVIRONMENT.workingDir); - expect(response.stderr.toString()).toContain("command 'profiles list base-profiles' is deprecated"); - expect(response.status).toBe(0); + response = runCliScript(__dirname + "/__scripts__/show_profiles.sh", TEST_ENVIRONMENT.workingDir); + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).not.toContain("tokenType:"); expect(response.stdout.toString()).not.toContain("tokenValue:"); + expect(response.status).toBe(0); }); - it("should create a profile, if requested 1", () => { - let response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_create_profile.sh", + it("should store token from cmd line user & password - y", () => { + let response = runCliScript(__dirname + "/__scripts__/auth_login_cmd_line_password.sh", TEST_ENVIRONMENT.workingDir, ["y", "fakeUser", "fakePass"]); expect(response.stderr.toString()).toBe(""); - expect(response.status).toBe(0); expect(response.stdout.toString()).toContain("Login successful."); - expect(response.stdout.toString()).toContain("The authentication token is stored in the 'default' base profile"); - - response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_show_profiles.sh", TEST_ENVIRONMENT.workingDir); - - expect(response.stderr.toString()).toContain("command 'profiles list base-profiles' is deprecated"); + expect(response.stdout.toString()).toContain( + "The authentication token is stored in the 'baseProfName' base profile for future use"); expect(response.status).toBe(0); + + response = runCliScript(__dirname + "/__scripts__/show_profiles.sh", TEST_ENVIRONMENT.workingDir); + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("host: fakeHost"); expect(response.stdout.toString()).toContain("port: 3000"); expect(response.stdout.toString()).toContain("tokenType: jwtToken"); - expect(response.stdout.toString()).toContain("tokenValue: fakeUser:fakePass@fakeToken"); + expect(response.stdout.toString()).toContain("tokenValue: (secure value)"); expect(response.stdout.toString()).not.toContain("user:"); expect(response.stdout.toString()).not.toContain("password:"); + expect(response.status).toBe(0); }); - it("should create a profile, if requested 2", () => { - let response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_create_profile.sh", + it("should store token from cmd line user & password - yes", () => { + let response = runCliScript(__dirname + "/__scripts__/auth_login_cmd_line_password.sh", TEST_ENVIRONMENT.workingDir, ["yes", "fakeUser", "fakePass"]); expect(response.stderr.toString()).toBe(""); - expect(response.status).toBe(0); expect(response.stdout.toString()).toContain("Login successful."); - expect(response.stdout.toString()).toContain("The authentication token is stored in the 'default' base profile"); - - response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_show_profiles.sh", TEST_ENVIRONMENT.workingDir); - - expect(response.stderr.toString()).toContain("command 'profiles list base-profiles' is deprecated"); + expect(response.stdout.toString()).toContain( + "The authentication token is stored in the 'baseProfName' base profile for future use"); expect(response.status).toBe(0); + + response = runCliScript(__dirname + "/__scripts__/show_profiles.sh", TEST_ENVIRONMENT.workingDir); + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("host: fakeHost"); expect(response.stdout.toString()).toContain("port: 3000"); expect(response.stdout.toString()).toContain("tokenType: jwtToken"); - expect(response.stdout.toString()).toContain("tokenValue: fakeUser:fakePass@fakeToken"); + expect(response.stdout.toString()).toContain("tokenValue: (secure value)"); expect(response.stdout.toString()).not.toContain("user:"); expect(response.stdout.toString()).not.toContain("password:"); + expect(response.status).toBe(0); }); - it("should create a profile, if requested 3", () => { - let response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_create_profile_cert.sh", + it("should store token from cmd line certificate", () => { + let response = runCliScript(__dirname + "/__scripts__/auth_login_cmd_line_cert.sh", TEST_ENVIRONMENT.workingDir, ["y", fakeCertPath, fakeCertKeyPath]); expect(response.stderr.toString()).toBe(""); - expect(response.status).toBe(0); expect(response.stdout.toString()).toContain("Login successful."); - expect(response.stdout.toString()).toContain("The authentication token is stored in the 'default' base profile"); - - response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_show_profiles.sh", TEST_ENVIRONMENT.workingDir); - - expect(response.stderr.toString()).toContain("command 'profiles list base-profiles' is deprecated"); + expect(response.stdout.toString()).toContain( + "The authentication token is stored in the 'baseProfName' base profile for future use"); expect(response.status).toBe(0); - expect(response.stdout.toString()).toContain("certFile: " + fakeCertPath); - expect(response.stdout.toString()).toContain("certKeyFile: " + fakeCertKeyPath); - expect(response.stdout.toString()).toContain("host: fakeHost"); - expect(response.stdout.toString()).toContain("port: 3000"); - expect(response.stdout.toString()).toContain("tokenType: jwtToken"); - expect(response.stdout.toString()).toContain("tokenValue: fakeCertificate@fakeToken"); + + response = runCliScript(__dirname + "/__scripts__/show_profiles.sh", TEST_ENVIRONMENT.workingDir); + expect(response.stderr.toString()).toBe(""); + expect(response.stdout.toString()).toContain("host: fakeHost"); + expect(response.stdout.toString()).toContain("port: 3000"); + expect(response.stdout.toString()).toContain("tokenType: jwtToken"); + expect(response.stdout.toString()).toContain("secure"); + expect(response.stdout.toString()).toContain("tokenValue"); expect(response.stdout.toString()).not.toContain("user:"); expect(response.stdout.toString()).not.toContain("password:"); + expect(response.stdout.toString()).not.toContain("certFile:"); + expect(response.stdout.toString()).not.toContain("certKeyFile:"); + expect(response.status).toBe(0); }); - it("should not create a profile, if requested 1", () => { - let response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_create_profile.sh", + it("should NOT store token from user & password, if requested", () => { + let response = runCliScript(__dirname + "/__scripts__/auth_login_cmd_line_password.sh", TEST_ENVIRONMENT.workingDir, ["n", "fakeUser", "fakePass"]); - expect(response.status).toBe(0); + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("Login successful."); expect(response.stdout.toString()).toContain("will not be stored in your profile"); expect(response.stdout.toString()).toContain("fakeUser:fakePass@fakeToken"); - - response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_show_profiles.sh", TEST_ENVIRONMENT.workingDir); - - expect(response.stderr.toString()).toContain("command 'profiles list base-profiles' is deprecated"); expect(response.status).toBe(0); + + response = runCliScript(__dirname + "/__scripts__/show_profiles.sh", TEST_ENVIRONMENT.workingDir); + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).not.toContain("user:"); expect(response.stdout.toString()).not.toContain("password:"); expect(response.stdout.toString()).not.toContain("host:"); expect(response.stdout.toString()).not.toContain("port:"); expect(response.stdout.toString()).not.toContain("tokenType:"); expect(response.stdout.toString()).not.toContain("tokenValue:"); + expect(response.status).toBe(0); }); - it("should not create a profile, if requested 2", () => { - let response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_create_profile_cert.sh", + it("should NOT store token from cert, if requested", () => { + let response = runCliScript(__dirname + "/__scripts__/auth_login_cmd_line_cert.sh", TEST_ENVIRONMENT.workingDir, ["n", fakeCertPath, fakeCertKeyPath]); - expect(response.status).toBe(0); + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("Login successful."); expect(response.stdout.toString()).toContain("will not be stored in your profile"); expect(response.stdout.toString()).toContain("fakeCertificate@fakeToken"); - - response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login_show_profiles.sh", TEST_ENVIRONMENT.workingDir); - - expect(response.stderr.toString()).toContain("command 'profiles list base-profiles' is deprecated"); expect(response.status).toBe(0); + + response = runCliScript(__dirname + "/__scripts__/show_profiles.sh", TEST_ENVIRONMENT.workingDir); + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).not.toContain("user:"); expect(response.stdout.toString()).not.toContain("password:"); expect(response.stdout.toString()).not.toContain("host:"); @@ -252,5 +228,6 @@ describe("cmd-cli auth login", () => { expect(response.stdout.toString()).not.toContain("tokenValue:"); expect(response.stdout.toString()).not.toContain("certFile:"); expect(response.stdout.toString()).not.toContain("certKeyFile:"); + expect(response.status).toBe(0); }); }); diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/Cmd.cli.auth.logout.fruit.integration.subtest.ts b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/Cmd.cli.auth.logout.fruit.integration.subtest.ts index e8c09ee7ca..a71efbcb9a 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/Cmd.cli.auth.logout.fruit.integration.subtest.ts +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/Cmd.cli.auth.logout.fruit.integration.subtest.ts @@ -12,11 +12,10 @@ import { runCliScript } from "../../../../../../src/TestUtil"; import { ITestEnvironment } from "../../../../../../__src__/environment/doc/response/ITestEnvironment"; import { SetupTestEnvironment } from "../../../../../../__src__/environment/SetupTestEnvironment"; -import { join } from "path"; // Test Environment populated in the beforeAll(); let TEST_ENVIRONMENT: ITestEnvironment; -describe("cmd-cli auth logout", () => { +describe("imperative-test-cli auth logout", () => { // Create the unique test environment beforeAll(async () => { TEST_ENVIRONMENT = await SetupTestEnvironment.createTestEnv({ @@ -25,69 +24,71 @@ describe("cmd-cli auth logout", () => { }); }); - afterEach(() => { - // delete profiles between tests so that they can be recreated - require("rimraf").sync(join(TEST_ENVIRONMENT.workingDir, "profiles")); - }); - - it("should have auth logout command that loads values from base profile and removes the token with alias", () => { - let response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_li.sh", - TEST_ENVIRONMENT.workingDir, ["fakeUser", "fakePass"]); - expect(response.stderr.toString()).toContain("command 'profiles create base-profile' is deprecated"); - expect(response.status).toBe(0); + it("should have auth lo command that loads values from base profile and removes the token", () => { + let response = runCliScript(__dirname + "/__scripts__/auth_li_config_password.sh", + TEST_ENVIRONMENT.workingDir); - // the output of the command should include token value + // the output of the login command should include token value + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("tokenType: jwtToken"); - expect(response.stdout.toString()).toContain("tokenValue: fakeUser:fakePass@fakeToken"); + expect(response.stdout.toString()).toContain("tokenValue: (secure value)"); + expect(response.status).toBe(0); - response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_lo.sh", + response = runCliScript(__dirname + "/__scripts__/auth_lo.sh", TEST_ENVIRONMENT.workingDir); - expect(response.stderr.toString()).toContain("command 'profiles list base-profiles' is deprecated"); - expect(response.status).toBe(0); - // the output of the command should include token value + // the output of the command should NOT include token value + expect(response.stderr.toString()).toBe(""); + expect(response.stdout.toString()).toContain("Logout successful. The authentication token has been revoked"); + expect(response.stdout.toString()).toContain("Token was removed from your 'baseProfName_fruit' base profile"); expect(response.stdout.toString()).not.toContain("tokenType:"); expect(response.stdout.toString()).not.toContain("tokenValue:"); + expect(response.status).toBe(0); }); it("should have auth logout command that loads values from base profile and removes the token", () => { - let response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login.sh", - TEST_ENVIRONMENT.workingDir, ["fakeUser", "fakePass"]); - expect(response.stderr.toString()).toContain("command 'profiles create base-profile' is deprecated"); - expect(response.status).toBe(0); + let response = runCliScript(__dirname + "/__scripts__/auth_login_config_password.sh", + TEST_ENVIRONMENT.workingDir); - // the output of the command should include token value + // the output of the login command should include token value + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("tokenType: jwtToken"); - expect(response.stdout.toString()).toContain("tokenValue: fakeUser:fakePass@fakeToken"); + expect(response.stdout.toString()).toContain("tokenValue: (secure value)"); + expect(response.status).toBe(0); - response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_logout.sh", + response = runCliScript(__dirname + "/__scripts__/auth_logout.sh", TEST_ENVIRONMENT.workingDir); - expect(response.stderr.toString()).toContain("command 'profiles list base-profiles' is deprecated"); - expect(response.status).toBe(0); - // the output of the command should include token value + // the output of the command should NOT include token value + expect(response.stderr.toString()).toBe(""); + expect(response.stdout.toString()).toContain("Logout successful. The authentication token has been revoked"); + expect(response.stdout.toString()).toContain("Token was removed from your 'baseProfName_fruit' base profile"); expect(response.stdout.toString()).not.toContain("tokenType:"); expect(response.stdout.toString()).not.toContain("tokenValue:"); + expect(response.status).toBe(0); }); it("should have auth logout command that invalidates another token", () => { - let response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_login.sh", - TEST_ENVIRONMENT.workingDir, ["fakeUser", "fakePass"]); - expect(response.stderr.toString()).toContain("command 'profiles create base-profile' is deprecated"); - expect(response.stderr.toString()).toContain("command 'profiles list base-profiles' is deprecated"); - expect(response.status).toBe(0); + let response = runCliScript(__dirname + "/__scripts__/auth_login_config_password.sh", + TEST_ENVIRONMENT.workingDir); - // the output of the command should include token value + // the output of the login command should include token value + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("tokenType: jwtToken"); - expect(response.stdout.toString()).toContain("tokenValue: fakeUser:fakePass@fakeToken"); + expect(response.stdout.toString()).toContain("tokenValue: (secure value)"); + expect(response.status).toBe(0); + - response = runCliScript(__dirname + "/__scripts__/base_profile_and_auth_logout_specify_token.sh", + response = runCliScript(__dirname + "/__scripts__/auth_logout_specify_token.sh", TEST_ENVIRONMENT.workingDir, ["fakeToken:fakeToken@fakeToken"]); - expect(response.stderr.toString()).toContain("command 'profiles list base-profiles' is deprecated"); - expect(response.status).toBe(0); - // the output of the command should include token value + // the output of the command should still include token value + expect(response.stderr.toString()).toBe(""); + expect(response.stdout.toString()).toContain("Logout successful. The authentication token has been revoked"); + expect(response.stdout.toString()).toContain("Token was not removed from your 'baseProfName_fruit' base profile"); + expect(response.stdout.toString()).toContain("Reason: Token value does not match the securely stored value"); expect(response.stdout.toString()).toContain("tokenType: jwtToken"); - expect(response.stdout.toString()).toContain("tokenValue: fakeUser:fakePass@fakeToken"); + expect(response.stdout.toString()).toContain("tokenValue: (secure value)"); + expect(response.status).toBe(0); }); }); diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__resources__/base_cert.config.json b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__resources__/base_cert.config.json new file mode 100644 index 0000000000..028bd34bbc --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__resources__/base_cert.config.json @@ -0,0 +1,15 @@ +{ + "profiles": { + "baseProfName": { + "type": "base", + "properties": { + "certFile": "./fakeCert.cert", + "certKeyFile": "./fakeKey.key" + } + } + }, + "defaults": { + "base": "baseProfName" + }, + "autoStore": true +} \ No newline at end of file diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__resources__/base_password.config.json b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__resources__/base_password.config.json new file mode 100644 index 0000000000..b636e8376f --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__resources__/base_password.config.json @@ -0,0 +1,15 @@ +{ + "profiles": { + "baseProfName": { + "type": "base", + "properties": { + "user": "fakeUser", + "password": "fakePass" + } + } + }, + "defaults": { + "base": "baseProfName" + }, + "autoStore": true +} \ No newline at end of file diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_li_config_password.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_li_config_password.sh new file mode 100644 index 0000000000..09bc2741e1 --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_li_config_password.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# copy our config file +cp $myScriptDir/../__resources__/base_password.config.json imperative-test-cli.config.json +exitOnFailure "Failed to copy config file." $? + +# login to fruit auth +echo Y | imperative-test-cli auth li fruit +exitOnFailure "Logging into auth of type fruit failed!" $? + +# show contents of our config file +imperative-test-cli config list profiles +exitOnFailure "Display of updated imperative-test-cli.config.json failed!" $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_lo.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_lo.sh new file mode 100644 index 0000000000..e81be2cf7d --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_lo.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +imperative-test-cli auth lo fruit +exitOnFailure "Logging out auth of type fruit failed!" $? + +# show contents of our config file +imperative-test-cli config list profiles +exitOnFailure "Display of updated imperative-test-cli.config.json failed!" $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_cmd_line_cert.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_cmd_line_cert.sh new file mode 100644 index 0000000000..28214cb99d --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_cmd_line_cert.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +echoVal=${1:?"First parm (echoVal) is required."} +baseCertFile=${2:?"Second parm (baseCertFile) is required."} +baseCertKey=${3:?"Third parm (baseCertKey) is required."} + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# copy our config file and certificate files +resourceDir=$myScriptDir/../__resources__ +cp $resourceDir/base_cert.config.json . +exitOnFailure "Failed to copy config file." $? + +cp $resourceDir/$baseCertFile . +exitOnFailure "Failed to copy certificate file." $? + +cp $resourceDir/$baseCertKey . +exitOnFailure "Failed to copy certificate key file." $? + +# remove existing cert from our config file +sed -e '/"certFile":/d' -e '/"certKeyFile":/d' < base_cert.config.json > imperative-test-cli.config.json +exitOnFailure "Failed to update config file." $? + +echo $echoVal | imperative-test-cli auth login fruit --certFile "$baseCertFile" --certKeyFile "$baseCertKey" +exitOnFailure "Logging into auth of type fruit failed!" $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_cmd_line_password.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_cmd_line_password.sh new file mode 100644 index 0000000000..4e7d107694 --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_cmd_line_password.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +echoVal=${1:?"First parm (echoVal) is required."} +baseUser=${2:?"Second parm (baseUser) is required."} +basePass=${3:?"Third parm (basePass) is required."} + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# copy our config file +cp $myScriptDir/../__resources__/base_password.config.json . +exitOnFailure "Failed to copy config file." $? + +# remove existing user and password from our config file +sed -e '/"user":/d' -e '/"password":/d' < base_password.config.json > imperative-test-cli.config.json +exitOnFailure "Failed to update config file." $? + +echo $echoVal | imperative-test-cli auth login fruit --user "$baseUser" --password "$basePass" +exitOnFailure "Logging into auth of type fruit failed!" $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_cert.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_cert.sh new file mode 100644 index 0000000000..f14b6c3ac8 --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_cert.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# copy our config file and certificate files +resourceDir=$myScriptDir/../__resources__ +cp $resourceDir/base_cert.config.json imperative-test-cli.config.json +exitOnFailure "Failed to copy config file." $? + +cp $resourceDir/fakeCert.cert . +exitOnFailure "Failed to copy certificate file." $? + +cp $resourceDir/fakeKey.key . +exitOnFailure "Failed to copy certificate key file." $? + +# login to fruit auth +echo Y | imperative-test-cli auth login fruit +exitOnFailure "Logging into auth of type fruit failed!" $? + +# show contents of our config file +imperative-test-cli config list profiles +exitOnFailure "Display of updated imperative-test-cli.config.json failed!" $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_cert_show_token.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_cert_show_token.sh new file mode 100644 index 0000000000..0bf0457c25 --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_cert_show_token.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# copy our config file and certificate files +resourceDir=$myScriptDir/../__resources__ +cp $resourceDir/base_cert.config.json imperative-test-cli.config.json +exitOnFailure "Failed to copy config file." $? + +cp $resourceDir/fakeCert.cert . +exitOnFailure "Failed to copy certificate file." $? + +cp $resourceDir/fakeKey.key . +exitOnFailure "Failed to copy certificate key file." $? + +# login to fruit auth +imperative-test-cli auth login fruit --show-token +exitOnFailure "Logging into auth of type fruit failed!" $? + +# show contents of our config file +imperative-test-cli config list profiles +exitOnFailure "Display of updated imperative-test-cli.config.json failed!" $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_cert_show_token_rfj.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_cert_show_token_rfj.sh new file mode 100644 index 0000000000..1dd06409ed --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_cert_show_token_rfj.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# copy our config file +cp $myScriptDir/../__resources__/base_cert.config.json imperative-test-cli.config.json +exitOnFailure "Failed to copy config file." $? + +# Login to fruit auth. Only show token. Do not store token. +imperative-test-cli auth login fruit --st --rfj +exitOnFailure "Logging into auth of type fruit failed!" $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_password.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_password.sh new file mode 100644 index 0000000000..0671508979 --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_password.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# copy our config file +cp $myScriptDir/../__resources__/base_password.config.json imperative-test-cli.config.json +exitOnFailure "Failed to copy config file." $? + +# login to fruit auth +echo Y | imperative-test-cli auth login fruit +exitOnFailure "Logging into auth of type fruit failed!" $? + +# show contents of our config file +imperative-test-cli config list profiles +exitOnFailure "Display of updated imperative-test-cli.config.json failed!" $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_password_show_token.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_password_show_token.sh new file mode 100644 index 0000000000..2aec38d48e --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_password_show_token.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# copy our config file +cp $myScriptDir/../__resources__/base_password.config.json imperative-test-cli.config.json +exitOnFailure "Failed to copy config file." $? + +# login to fruit auth +imperative-test-cli auth login fruit --show-token +exitOnFailure "Logging into auth of type fruit failed!" $? + +# show contents of our config file +imperative-test-cli config list profiles +exitOnFailure "Display of updated imperative-test-cli.config.json failed!" $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_password_show_token_rfj.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_password_show_token_rfj.sh new file mode 100644 index 0000000000..d7ae8a3693 --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_login_config_password_show_token_rfj.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# copy our config file +cp $myScriptDir/../__resources__/base_password.config.json imperative-test-cli.config.json +exitOnFailure "Failed to copy config file." $? + +# Login to fruit auth. Only show token. Do not store token. +imperative-test-cli auth login fruit --st --rfj +exitOnFailure "Logging into auth of type fruit failed!" $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_logout.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_logout.sh new file mode 100644 index 0000000000..5b86c86718 --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_logout.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +imperative-test-cli auth logout fruit +exitOnFailure "Logging out auth of type fruit failed!" $? + +# show contents of our config file +imperative-test-cli config list profiles +exitOnFailure "Display of updated imperative-test-cli.config.json failed!" $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_logout_specify_token.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_logout_specify_token.sh new file mode 100644 index 0000000000..b5d49de297 --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/auth_logout_specify_token.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +tokenValue=$1 + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +imperative-test-cli auth logout fruit --token-value "$tokenValue" +exitOnFailure "Logging out auth of type fruit failed!" $? + +# show contents of our config file +imperative-test-cli config list profiles +exitOnFailure "Display of updated imperative-test-cli.config.json failed!" $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_li.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_li.sh deleted file mode 100644 index b2807c13e5..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_li.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -baseUser=$1 -basePass=$2 - -# First create a base profile -cmd-cli profiles create base-profile "test_base" --user "$baseUser" --password "$basePass" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_base profile of type base failed!" 1>&2 - exit $CMDRC -fi - -# Next login to fruit auth -cmd-cli auth li fruit -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Logging into auth of type fruit failed!" 1>&2 - exit $CMDRC -fi - -# Now show contents of base profile -cmd-cli profiles list base-profiles --sc -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Listing profiles of type base failed!" 1>&2 - exit $CMDRC -fi diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_lo.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_lo.sh deleted file mode 100644 index 16a3af4bfc..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_lo.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -# Next logout of fruit auth -cmd-cli auth lo fruit -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Logging out of auth of type fruit failed!" 1>&2 - exit $CMDRC -fi - -# Now show contents of base profile -cmd-cli profiles list base-profiles --sc -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Listing profiles of type base failed!" 1>&2 - exit $CMDRC -fi diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login.sh deleted file mode 100644 index b8eff2b07e..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -baseUser=$1 -basePass=$2 - -# First create a base profile -cmd-cli profiles create base-profile "test_base" --user "$baseUser" --password "$basePass" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_base profile of type base failed!" 1>&2 - exit $CMDRC -fi - -# Next login to fruit auth -cmd-cli auth login fruit -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Logging into auth of type fruit failed!" 1>&2 - exit $CMDRC -fi - -# Now show contents of base profile -cmd-cli profiles list base-profiles --sc -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Listing profiles of type base failed!" 1>&2 - exit $CMDRC -fi diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_cert.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_cert.sh deleted file mode 100644 index 2e2dadbb15..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_cert.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -baseCertFile=$1 -baseCertKey=$2 - -# First create a base profile -cmd-cli profiles create base-profile "test_base" --certFile "$baseCertFile" --certKeyFile "$baseCertKey" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_base profile of type base failed!" 1>&2 - exit $CMDRC -fi - -# Next login to fruit auth -cmd-cli auth login fruit -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Logging into auth of type fruit failed!" 1>&2 - exit $CMDRC -fi - -# Now show contents of base profile -cmd-cli profiles list base-profiles --sc -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Listing profiles of type base failed!" 1>&2 - exit $CMDRC -fi diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_create_profile.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_create_profile.sh deleted file mode 100644 index 3301161aad..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_create_profile.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -echoVal=$1 -baseUser=$2 -basePass=$3 - -echo $echoVal | cmd-cli auth login fruit --user "$baseUser" --password "$basePass" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Logging into auth of type fruit failed!" 1>&2 - exit $CMDRC -fi \ No newline at end of file diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_create_profile_cert.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_create_profile_cert.sh deleted file mode 100644 index a900ff0260..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_create_profile_cert.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -echoVal=$1 -baseCertFile=$2 -baseCertKey=$3 - -echo $echoVal | cmd-cli auth login fruit --certFile "$baseCertFile" --certKeyFile "$baseCertKey" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Logging into auth of type fruit failed!" 1>&2 - exit $CMDRC -fi \ No newline at end of file diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_show_profiles.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_show_profiles.sh deleted file mode 100644 index 72e83fb7ed..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_show_profiles.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -# Now show contents of base profile -cmd-cli profiles list base-profiles --sc -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Listing profiles of type base failed!" 1>&2 - exit $CMDRC -fi diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_show_token.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_show_token.sh deleted file mode 100644 index 20a8c6b370..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_show_token.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -baseUser=$1 -basePass=$2 - -# First create a base profile -cmd-cli profiles create base-profile "test_base" --user "$baseUser" --password "$basePass" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_base profile of type base failed!" 1>&2 - exit $CMDRC -fi - -# Next login to fruit auth -cmd-cli auth login fruit --show-token -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Logging into auth of type fruit failed!" 1>&2 - exit $CMDRC -fi diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_show_token_cert.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_show_token_cert.sh deleted file mode 100644 index a996a1b5c8..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_show_token_cert.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -baseCertFile=$1 -baseCertKey=$2 - -# First create a base profile -cmd-cli profiles create base-profile "test_base" --certFile "$baseCertFile" --certKeyFile "$baseCertKey" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_base profile of type base failed!" 1>&2 - exit $CMDRC -fi - -# Next login to fruit auth -cmd-cli auth login fruit --show-token -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Logging into auth of type fruit failed!" 1>&2 - exit $CMDRC -fi diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_show_token_rfj.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_show_token_rfj.sh deleted file mode 100644 index 3bb985706d..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_login_show_token_rfj.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -# Next login to fruit auth -cmd-cli auth login fruit --st --rfj -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Logging into auth of type fruit failed!" 1>&2 - exit $CMDRC -fi diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_logout.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_logout.sh deleted file mode 100644 index f5638b1967..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_logout.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -# Next logout of fruit auth -cmd-cli auth logout fruit -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Logging out of auth of type fruit failed!" 1>&2 - exit $CMDRC -fi - -# Now show contents of base profile -cmd-cli profiles list base-profiles --sc -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Listing profiles of type base failed!" 1>&2 - exit $CMDRC -fi diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_logout_specify_token.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_logout_specify_token.sh deleted file mode 100644 index 33541b4373..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_and_auth_logout_specify_token.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -tokenValue=$1 - -# Next logout of fruit auth -cmd-cli auth logout fruit --token-value "$tokenValue" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Logging out of auth of type fruit failed!" 1>&2 - exit $CMDRC -fi - -# Now show contents of base profile -cmd-cli profiles list base-profiles --sc -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Listing profiles of type base failed!" 1>&2 - exit $CMDRC -fi diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_create.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_create.sh deleted file mode 100644 index 921c1be86d..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_create.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -baseUser=$1 -basePass=$2 - -# First create a base profile -cmd-cli profiles create base-profile "test_base" --user "$baseUser" --password "$basePass" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_base profile of type base failed!" 1>&2 - exit $CMDRC -fi diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_create_cert.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_create_cert.sh deleted file mode 100644 index 5495f01f74..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/base_profile_create_cert.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -baseCertFile=$1 -baseCertKey=$2 - -# First create a base profile -cmd-cli profiles create base-profile "test_base" --certFile "$baseCertFile" --certKeyFile "$baseCertKey" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_base profile of type base failed!" 1>&2 - exit $CMDRC -fi diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/show_profiles.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/show_profiles.sh new file mode 100644 index 0000000000..88190d9ac0 --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/auth/__scripts__/show_profiles.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# This script must be called AFTER a script copies a config file into our test directory. + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# show contents of our config file +imperative-test-cli config list profiles +exitOnFailure "Display of updated imperative-test-cli.config.json failed!" $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/chained/Cmd.cli.chainedhandlers.integration.test.ts b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/chained/Cmd.cli.chainedhandlers.integration.test.ts index 27f8ce6960..151002209e 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/chained/Cmd.cli.chainedhandlers.integration.test.ts +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/chained/Cmd.cli.chainedhandlers.integration.test.ts @@ -27,21 +27,6 @@ describe("cmd-cli chained handlers", () => { }); }); - // eslint-disable-next-line deprecation/deprecation - const mainModule = process.mainModule; - - beforeEach(() => { - // eslint-disable-next-line deprecation/deprecation - (process.mainModule as any) = { - filename: __filename - }; - }); - - afterEach(() => { - // eslint-disable-next-line deprecation/deprecation - process.mainModule = mainModule; - }); - it("should not allow us to configure chained handlers that map arguments to indices beyond " + "the end of the list of chained handlers (edge case - one beyond the length of the array)", async () => { const fakeHandler = "my_handler_here"; diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invalid/Cmd.cli.invalid.profile-spec.integration.test.ts b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invalid/Cmd.cli.invalid.profile-spec.integration.test.ts deleted file mode 100644 index 5da118c9ad..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invalid/Cmd.cli.invalid.profile-spec.integration.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ITestEnvironment } from "../../../../../../__src__/environment/doc/response/ITestEnvironment"; -import { SetupTestEnvironment } from "../../../../../../__src__/environment/SetupTestEnvironment"; -import { runCliScript } from "../../../../../../src/TestUtil"; - - -let TEST_ENVIRONMENT: ITestEnvironment; - -describe("cmd-cli invalid profile-spec", () => { - // Create the unique test environment - beforeAll(async () => { - TEST_ENVIRONMENT = await SetupTestEnvironment.createTestEnv({ - cliHomeEnvVar: "CMD_CLI_CLI_HOME", - testName: "cmd_cli_invalid_profile_spec" - }); - }); - - it("should fail the command if the profile property is not supplied and the handler requests a profile", () => { - const response = runCliScript(__dirname + "/__scripts__/profile-spec.sh", TEST_ENVIRONMENT.workingDir); - expect(response.status).toBe(1); - expect(response.stdout.toString()).toBe(""); - expect(response.stderr.toString()).toMatchSnapshot(); - }); -}); diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invalid/__scripts__/profile-spec.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invalid/__scripts__/profile-spec.sh deleted file mode 100644 index 1879d239cd..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invalid/__scripts__/profile-spec.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -cmd-cli invalid profile-spec -exit $? \ No newline at end of file diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invalid/__snapshots__/Cmd.cli.invalid.profile-spec.integration.test.ts.snap b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invalid/__snapshots__/Cmd.cli.invalid.profile-spec.integration.test.ts.snap deleted file mode 100644 index a37ab9cb29..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invalid/__snapshots__/Cmd.cli.invalid.profile-spec.integration.test.ts.snap +++ /dev/null @@ -1,11 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`cmd-cli invalid profile-spec should fail the command if the profile property is not supplied and the handler requests a profile 1`] = ` -"Command Error: -Internal Error: No profiles of type \\"blah\\" were loaded for this command. -Error Details: -This error can occur for one of two reasons: - - The \\"profile\\" property on the command definition document does NOT specify the requested profile type - - The profile type is marked \\"optional\\", no profiles of type \\"blah\\" have been created, and the command handler requested a profile of type \\"blah\\" with \\"failNotFound=true\\" -" -`; diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/Cmd.cli.invoke.exit143.integration.test.ts b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/Cmd.cli.invoke.exit143.integration.test.ts index 548d00c08d..f883d76897 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/Cmd.cli.invoke.exit143.integration.test.ts +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/Cmd.cli.invoke.exit143.integration.test.ts @@ -30,6 +30,7 @@ describe("cmd-cli invoke exit 143", () => { const response = runCliScript(__dirname + "/__scripts__/exit/exit_143.sh", TEST_ENVIRONMENT.workingDir); expect(response.status).toBe(ONE_FOUR_THREE); - expect(response.stderr.toString()).toMatchSnapshot(); + expect(response.stdout.toString()).toBe(""); + expect(response.stderr.toString()).toContain("Command failed with exit code 143"); }); }); diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/Cmd.cli.invoke.test-async-handler.integration.test.ts b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/Cmd.cli.invoke.test-async-handler.integration.test.ts index 951dde75b5..8329e31724 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/Cmd.cli.invoke.test-async-handler.integration.test.ts +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/Cmd.cli.invoke.test-async-handler.integration.test.ts @@ -47,8 +47,16 @@ describe("cmd-cli invoke test-async-handler", () => { const response = runCliScript(__dirname + "/__scripts__/test-async-handler/invoke_test_async_handler_fail_ie.sh", TEST_ENVIRONMENT.workingDir); expect(response.status).toBe(1); - expect(response.stderr.toString()).toMatchSnapshot(); - expect(response.stdout.toString()).toMatchSnapshot(); + expect(response.stderr.toString()).toContain("Fail with Imperative Error"); + expect(response.stdout.toString()).toContain("===================FAIL WITH IMPERATIVE ERROR============================"); + expect(response.stdout.toString()).toContain("===================FAIL WITH IMPERATIVE ERROR RFJ========================"); + expect(response.stdout.toString()).toContain('"success": false'); + expect(response.stdout.toString()).toContain('"exitCode": 1'); + expect(response.stdout.toString()).toContain('"message": "Fail with Imperative Error"'); + expect(response.stdout.toString()).toContain('"stdout":'); + expect(response.stdout.toString()).toContain('"data":'); + expect(response.stdout.toString()).toContain('"error":'); + expect(response.stdout.toString()).toContain('"msg": "Fail with Imperative Error"'); }); it("should fail a handler if a generic error is thrown", async () => { diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/__snapshots__/Cmd.cli.invoke.exit143.integration.test.ts.snap b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/__snapshots__/Cmd.cli.invoke.exit143.integration.test.ts.snap deleted file mode 100644 index 97332865c3..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/__snapshots__/Cmd.cli.invoke.exit143.integration.test.ts.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`cmd-cli invoke exit 143 should allow a handler to set an exit code and throw an error 1`] = ` -"Command Error: -Command failed with exit code 143 -" -`; diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/__snapshots__/Cmd.cli.invoke.integration.test.ts.snap b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/__snapshots__/Cmd.cli.invoke.integration.test.ts.snap index a575628f0d..5dcae7e651 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/__snapshots__/Cmd.cli.invoke.integration.test.ts.snap +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/__snapshots__/Cmd.cli.invoke.integration.test.ts.snap @@ -6,7 +6,7 @@ exports[`cmd-cli invoke should display help examples for a group 1`] = ` DESCRIPTION ----------- - Connect to token-based authentication services + Connect to token-based authentication services. USAGE ----- diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/__snapshots__/Cmd.cli.invoke.test-async-handler.integration.test.ts.snap b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/__snapshots__/Cmd.cli.invoke.test-async-handler.integration.test.ts.snap index b9a9e3d049..923aafc44f 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/__snapshots__/Cmd.cli.invoke.test-async-handler.integration.test.ts.snap +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/invoke/__snapshots__/Cmd.cli.invoke.test-async-handler.integration.test.ts.snap @@ -90,25 +90,3 @@ exports[`cmd-cli invoke test-async-handler should display the help 1`] = ` \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n test-async-handler\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Test async handler command tests tests a fulfill/reject from an asynchronous\\\\n handler.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n cmd-cli invoke test-async-handler [options]\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --fail (boolean)\\\\n\\\\n Fail the handler with an 'Imperative Error'.\\\\n\\\\n --fail-with-error (boolean)\\\\n\\\\n Fail the handler with a generic 'Error'.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\" }" `; - -exports[`cmd-cli invoke test-async-handler should fail a handler if an imperative error is thrown 1`] = ` -"Command Error: -Fail with Imperative Error -" -`; - -exports[`cmd-cli invoke test-async-handler should fail a handler if an imperative error is thrown 2`] = ` -"===================FAIL WITH IMPERATIVE ERROR============================ -===================FAIL WITH IMPERATIVE ERROR RFJ======================== -{ - \\"success\\": false, - \\"exitCode\\": 1, - \\"message\\": \\"Fail with Imperative Error\\", - \\"stdout\\": \\"\\", - \\"stderr\\": \\"Command Error:\\\\nFail with Imperative Error\\\\n\\", - \\"data\\": {}, - \\"error\\": { - \\"msg\\": \\"Fail with Imperative Error\\" - } -}" -`; diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/nested/Cmd.cli.nested.first-group.integration.test.ts b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/nested/Cmd.cli.nested.first-group.integration.test.ts index c72b87ed24..ee593928fc 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/nested/Cmd.cli.nested.first-group.integration.test.ts +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/nested/Cmd.cli.nested.first-group.integration.test.ts @@ -26,8 +26,8 @@ describe("cmd-cli nested first-group", () => { it("should display both groups and commands in the help", () => { const response = runCliScript(__dirname + "/__scripts__/first-group/first_group_help.sh", TEST_ENVIRONMENT.workingDir); - expect(response.status).toBe(0); expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); expect(response.stdout.toString()).toMatchSnapshot(); }); }); diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/nested/Cmd.cli.nested.integration.test.ts b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/nested/Cmd.cli.nested.integration.test.ts index 7297199cee..d82165e726 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/nested/Cmd.cli.nested.integration.test.ts +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/nested/Cmd.cli.nested.integration.test.ts @@ -25,8 +25,8 @@ describe("cmd-cli nested", () => { it("should display both groups and commands in the help", () => { const response = runCliScript(__dirname + "/__scripts__/nested/nested_help.sh", TEST_ENVIRONMENT.workingDir); - expect(response.status).toBe(0); expect(response.stderr.toString()).toBe(""); + expect(response.status).toBe(0); expect(response.stdout.toString()).toMatchSnapshot(); }); }); diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/Cmd.cli.profile.option.mapping.integration.test.ts b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/Cmd.cli.profile.option.mapping.integration.test.ts index ef6b906d59..9ac7152545 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/Cmd.cli.profile.option.mapping.integration.test.ts +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/Cmd.cli.profile.option.mapping.integration.test.ts @@ -35,14 +35,14 @@ describe("cmd-cli profile mapping", () => { const moldType = "none"; const response = runCliScript(__dirname + "/__scripts__/profiles/map_banana_to_options.sh", TEST_ENVIRONMENT.workingDir, [color, description, moldType]); - expect(response.stderr.toString()).toContain("The command 'profiles create banana-profile' is deprecated."); - expect(response.status).toBe(0); // the output of the command should use the profile values + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("Color: " + color); expect(response.stdout.toString()).toContain("Description: " + description); expect(response.stdout.toString()).toContain("Mold type: " + moldType); expect(response.stdout.toString()).toContain("Sweetness: mild"); + expect(response.status).toBe(0); }); it("should have command line arguments take precedence over profile fields", () => { @@ -55,14 +55,14 @@ describe("cmd-cli profile mapping", () => { const cliMoldType = "no mold at all"; const response = runCliScript(__dirname + "/__scripts__/profiles/banana_profile_and_specify_cli.sh", TEST_ENVIRONMENT.workingDir, [color, description, moldType, cliColor, cliDescription, cliMoldType]); - expect(response.stderr.toString()).toContain("The command 'profiles create banana-profile' is deprecated."); - expect(response.status).toBe(0); // the output of the command should use the CLI arguments + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("Color: " + cliColor); expect(response.stdout.toString()).toContain("Description: " + cliDescription); expect(response.stdout.toString()).toContain("Mold type: " + cliMoldType); expect(response.stdout.toString()).toContain("Sweetness: mild"); + expect(response.status).toBe(0); }); it("should have environmental variables take precedence over profile fields", () => { @@ -75,14 +75,14 @@ describe("cmd-cli profile mapping", () => { const envMoldType = "no mold at all"; const response = runCliScript(__dirname + "/__scripts__/profiles/banana_profile_and_specify_env.sh", TEST_ENVIRONMENT.workingDir, [color, description, moldType, envColor, envDescription, envMoldType]); - expect(response.stderr.toString()).toContain("The command 'profiles create banana-profile' is deprecated."); - expect(response.status).toBe(0); // the output of the command should use the env variable values + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("Color: " + envColor); expect(response.stdout.toString()).toContain("Description: " + envDescription); expect(response.stdout.toString()).toContain("Mold type: " + envMoldType); expect(response.stdout.toString()).toContain("Sweetness: mild"); + expect(response.status).toBe(0); }); it("should have command line arguments take precedence over profile fields and environmental variables", () => { @@ -102,14 +102,14 @@ describe("cmd-cli profile mapping", () => { const response = runCliScript(__dirname + "/__scripts__/profiles/banana_profile_and_specify_env_and_cli.sh", TEST_ENVIRONMENT.workingDir, [color, description, moldType, envColor, envDescription, envMoldType, cliColor, cliDescription, cliMoldType]); - expect(response.stderr.toString()).toContain("The command 'profiles create banana-profile' is deprecated."); - expect(response.status).toBe(0); // the output of the command should use the CLI arguments + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("Color: " + cliColor); expect(response.stdout.toString()).toContain("Description: " + cliDescription); expect(response.stdout.toString()).toContain("Mold type: " + cliMoldType); expect(response.stdout.toString()).toContain("Sweetness: mild"); + expect(response.status).toBe(0); }); it("should have environmental variables take precedence over default values", () => { @@ -123,15 +123,15 @@ describe("cmd-cli profile mapping", () => { const response = runCliScript(__dirname + "/__scripts__/profiles/specify_env_sweetness.sh", TEST_ENVIRONMENT.workingDir, [cliColor, cliDescription, cliMoldType, envSweetness]); - expect(response.stderr.toString()).toBe(""); - expect(response.status).toBe(0); // the output of the command should use the CLI arguments // except for sweetness which was specified by environmental variables + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("Color: " + cliColor); expect(response.stdout.toString()).toContain("Description: " + cliDescription); expect(response.stdout.toString()).toContain("Mold type: " + cliMoldType); expect(response.stdout.toString()).toContain("Sweetness: " + envSweetness); + expect(response.status).toBe(0); }); it("should have service profile fields take precedence over base profile fields", () => { @@ -140,13 +140,13 @@ describe("cmd-cli profile mapping", () => { const kiwiAmount = 1000; const response = runCliScript(__dirname + "/__scripts__/profiles/base_and_kiwi_profile.sh", TEST_ENVIRONMENT.workingDir, [baseAmount, basePrice, kiwiAmount]); - expect(response.stderr.toString()).toContain("The command 'profiles create kiwi-profile' is deprecated."); - expect(response.status).toBe(0); // the output of the command should use the base profile values // except for amount which was specified in service profile + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain(`Amount: ${kiwiAmount}`); expect(response.stdout.toString()).toContain(`Price: ${basePrice}`); + expect(response.status).toBe(0); }); it("should be able to specify positional options via environmental variables", () => { @@ -156,13 +156,13 @@ describe("cmd-cli profile mapping", () => { const envMoldType = "no mold at all"; const response = runCliScript(__dirname + "/__scripts__/profiles/specify_env_for_positional.sh", TEST_ENVIRONMENT.workingDir, [envColor, envDescription, envMoldType]); - expect(response.stderr.toString()).toBe(""); - expect(response.status).toBe(0); // the output of the command should use the env variable values + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("Color: " + envColor); expect(response.stdout.toString()).toContain("Description: " + envDescription); expect(response.stdout.toString()).toContain("Mold type: " + envMoldType); + expect(response.status).toBe(0); }); it("should map profile fields to positional options", () => { @@ -171,13 +171,13 @@ describe("cmd-cli profile mapping", () => { const moldType = "none"; const response = runCliScript(__dirname + "/__scripts__/profiles/map_banana_to_positionals.sh", TEST_ENVIRONMENT.workingDir, [color, description, moldType]); - expect(response.stderr.toString()).toContain("The command 'profiles create banana-profile' is deprecated."); - expect(response.status).toBe(0); // the output of the command should use the profile values + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("Color: " + color); expect(response.stdout.toString()).toContain("Description: " + description); expect(response.stdout.toString()).toContain("Mold type: " + moldType); + expect(response.status).toBe(0); }); it("should be able to specify valid number type options via environmental variables", () => { @@ -188,14 +188,14 @@ describe("cmd-cli profile mapping", () => { const envSides = "443"; const response = runCliScript(__dirname + "/__scripts__/profiles/specify_env_for_number.sh", TEST_ENVIRONMENT.workingDir, [cliColor, cliDescription, cliMoldType, envSides]); - expect(response.stderr.toString()).toBe(""); - expect(response.status).toBe(0); // the output of the command should use the env variable values + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("Color: " + cliColor); expect(response.stdout.toString()).toContain("Description: " + cliDescription); expect(response.stdout.toString()).toContain("Mold type: " + cliMoldType); expect(response.stdout.toString()).toContain("Sides: " + envSides); + expect(response.status).toBe(0); }); it("should get a syntax error when specifying a non-numeric value via environmental variables", () => { @@ -207,14 +207,17 @@ describe("cmd-cli profile mapping", () => { const response = runCliScript(__dirname + "/__scripts__/profiles/specify_env_for_number.sh", TEST_ENVIRONMENT.workingDir, [cliColor, cliDescription, cliMoldType, envSides]); - expect(response.stderr.toString()).toContain("failed!"); - expect(response.stderr.toString()).toContain("Syntax"); - expect(response.stderr.toString()).toContain("number"); + expect(response.stderr.toString()).toContain("Syntax Error"); + expect(response.stderr.toString()).toContain("Invalid value specified for option"); + expect(response.stderr.toString()).toContain("--sides"); + expect(response.stderr.toString()).toContain("You specified"); + expect(response.stderr.toString()).toContain(envSides); + expect(response.stderr.toString()).toContain("The value must be a number"); expect(response.stderr.toString()).toContain(envSides); expect(response.status).toBe(1); }); - it("should be able to specify valid boolean type options (true) via environmental variables", () => { + it("should be able to specify true boolean type options via environmental variables", () => { // values used as env variables const cliColor = "yellow and black"; const cliDescription = "A beautiful bunch of ripe banana hides the deadly black tarantula"; @@ -222,17 +225,17 @@ describe("cmd-cli profile mapping", () => { const envRipe = "true"; const response = runCliScript(__dirname + "/__scripts__/profiles/specify_env_for_boolean.sh", TEST_ENVIRONMENT.workingDir, [cliColor, cliDescription, cliMoldType, envRipe]); - expect(response.stderr.toString()).toBe(""); - expect(response.status).toBe(0); // the output of the command should use the env variable values + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("Color: " + cliColor); expect(response.stdout.toString()).toContain("Description: " + cliDescription); expect(response.stdout.toString()).toContain("Mold type: " + cliMoldType); expect(response.stdout.toString()).toContain("Ripe: true"); + expect(response.status).toBe(0); }); - it("should be able to specify valid boolean type options (false) via environmental variables", () => { + it("should be able to specify false boolean type options via environmental variables", () => { // values used as env variables const cliColor = "yellow and black"; const cliDescription = "A beautiful bunch of ripe banana hides the deadly black tarantula"; @@ -240,14 +243,14 @@ describe("cmd-cli profile mapping", () => { const envRipe = "false"; const response = runCliScript(__dirname + "/__scripts__/profiles/specify_env_for_boolean.sh", TEST_ENVIRONMENT.workingDir, [cliColor, cliDescription, cliMoldType, envRipe]); - expect(response.stderr.toString()).toBe(""); - expect(response.status).toBe(0); // the output of the command should use the env variable values + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("Color: " + cliColor); expect(response.stdout.toString()).toContain("Description: " + cliDescription); expect(response.stdout.toString()).toContain("Mold type: " + cliMoldType); expect(response.stdout.toString()).toContain("Ripe: false"); + expect(response.status).toBe(0); }); it("should get a syntax error when specifying a non-boolean value via environmental variables", () => { @@ -259,10 +262,12 @@ describe("cmd-cli profile mapping", () => { const response = runCliScript(__dirname + "/__scripts__/profiles/specify_env_for_boolean.sh", TEST_ENVIRONMENT.workingDir, [cliColor, cliDescription, cliMoldType, envRipe]); - expect(response.stderr.toString()).toContain("failed!"); - expect(response.stderr.toString()).toContain("Syntax"); - expect(response.stderr.toString()).toContain("boolean"); + expect(response.stderr.toString()).toContain("Syntax Error"); + expect(response.stderr.toString()).toContain("Invalid value specified for option"); + expect(response.stderr.toString()).toContain("--ripe (-r)"); + expect(response.stderr.toString()).toContain("You specified"); expect(response.stderr.toString()).toContain(envRipe); + expect(response.stderr.toString()).toContain("The value must be a boolean (true or false)"); expect(response.status).toBe(1); }); @@ -277,16 +282,16 @@ describe("cmd-cli profile mapping", () => { }).join(" "); const response = runCliScript(__dirname + "/__scripts__/profiles/specify_env_for_array.sh", TEST_ENVIRONMENT.workingDir, [cliColor, cliDescription, cliMoldType, envNames]); - expect(response.stderr.toString()).toBe(""); - expect(response.status).toBe(0); // the output of the command should use the env variable values + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("Color: " + cliColor); expect(response.stdout.toString()).toContain("Description: " + cliDescription); expect(response.stdout.toString()).toContain("Mold type: " + cliMoldType); for (const name of rawNames) { expect(response.stdout.toString()).toContain(name.replace("\\'", "'")); } + expect(response.status).toBe(0); }); it("should not map profile fields to --name or --type", () => { @@ -296,11 +301,11 @@ describe("cmd-cli profile mapping", () => { const moldType = "none"; const response = runCliScript(__dirname + "/__scripts__/profiles/name_type_undefined.sh", TEST_ENVIRONMENT.workingDir, [color, description, moldType]); - expect(response.stderr.toString()).toContain("The command 'profiles create banana-profile' is deprecated."); - expect(response.status).toBe(0); // name and type should be undefined since we did not specify them via command line + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("Name: undefined"); expect(response.stdout.toString()).toContain("Type: undefined"); + expect(response.status).toBe(0); }); it("should still be able to specify --name and --type on command line", () => { // values used as env variables @@ -311,10 +316,10 @@ describe("cmd-cli profile mapping", () => { const cliType = "Big"; const response = runCliScript(__dirname + "/__scripts__/profiles/name_type_specify.sh", TEST_ENVIRONMENT.workingDir, [color, description, moldType, cliName, cliType]); - expect(response.stderr.toString()).toContain("The command 'profiles create banana-profile' is deprecated."); - expect(response.status).toBe(0); // name and type should be undefined since we did not specify them via command line + expect(response.stderr.toString()).toBe(""); expect(response.stdout.toString()).toContain("Name: " + cliName); expect(response.stdout.toString()).toContain("Type: " + cliType); + expect(response.status).toBe(0); }); }); diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/Cmd.cli.profiles.create.banana-profile.integration.test.ts b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/Cmd.cli.profiles.create.banana-profile.integration.test.ts deleted file mode 100644 index b98b4104f3..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/Cmd.cli.profiles.create.banana-profile.integration.test.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { runCliScript } from "../../../../../../src/TestUtil"; -import { ITestEnvironment } from "../../../../../../__src__/environment/doc/response/ITestEnvironment"; -import { SetupTestEnvironment } from "../../../../../../__src__/environment/SetupTestEnvironment"; -// Test Environment populated in the beforeAll(); -let TEST_ENVIRONMENT: ITestEnvironment; -describe("cmd-cli profiles create banana", () => { - // Create the unique test environment - beforeAll(async () => { - TEST_ENVIRONMENT = await SetupTestEnvironment.createTestEnv({ - cliHomeEnvVar: "CMD_CLI_CLI_HOME", - testName: "cmd_profiles_create_banana" - }); - }); - - it("should create profiles and only list the type requested", () => { - - // Create a few profiles of multiple types - const response = runCliScript(__dirname + "/__scripts__/profiles/create_some_profiles.sh", TEST_ENVIRONMENT.workingDir); - expect(response.status).toBe(0); - expect(response.stderr.toString()).toContain("command 'profiles create banana-profile' is deprecated"); - expect(response.stdout.toString()).toContain("test_banana"); - expect(response.stdout.toString()).toContain("test_strawberry"); - expect(response.stdout.toString()).toContain("test_kiwi"); - expect(response.stdout.toString()).not.toContain("Overwrote existing profile"); - - // List the profiles for banana - const listBananaResponse = runCliScript(__dirname + "/__scripts__/profiles/list_profiles_of_type.sh", TEST_ENVIRONMENT.workingDir, - ["banana"]); - expect(listBananaResponse.status).toBe(0); - expect(listBananaResponse.stderr.toString()).toContain("command 'profiles list banana-profiles' is deprecated"); - expect(listBananaResponse.stdout.toString()).not.toContain("strawberry"); - expect(listBananaResponse.stdout.toString()).toMatchSnapshot(); - - // List the profiles for strawberry - const listStrawberryResponse = runCliScript(__dirname + "/__scripts__/profiles/list_profiles_of_type.sh", TEST_ENVIRONMENT.workingDir, - ["strawberry"]); - expect(listStrawberryResponse.status).toBe(0); - expect(listStrawberryResponse.stderr.toString()).toContain("command 'profiles list strawberry-profiles' is deprecated"); - expect(listStrawberryResponse.stdout.toString()).toMatchSnapshot(); - expect((listStrawberryResponse.stdout.toString().match(/default/g) || []).length).toBe(1); - - // List the profiles for kiwi - const listKiwiResponse = runCliScript(__dirname + "/__scripts__/profiles/list_profiles_of_type.sh", TEST_ENVIRONMENT.workingDir, ["kiwi"]); - expect(listKiwiResponse.status).toBe(0); - expect(listKiwiResponse.stderr.toString()).toContain("command 'profiles list kiwi-profiles' is deprecated"); - expect(listKiwiResponse.stdout.toString()).not.toContain("kiwiSecret"); - expect(listKiwiResponse.stdout.toString()).toMatchSnapshot(); - }); -}); diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/Cmd.cli.profiles.create.insecure.integration.test.ts b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/Cmd.cli.profiles.create.insecure.integration.test.ts deleted file mode 100644 index 841e8d257d..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/Cmd.cli.profiles.create.insecure.integration.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { runCliScript } from "../../../../../../src/TestUtil"; -import { ITestEnvironment } from "../../../../../../__src__/environment/doc/response/ITestEnvironment"; -import { SetupTestEnvironment } from "../../../../../../__src__/environment/SetupTestEnvironment"; -// Test Environment populated in the beforeAll(); -let TEST_ENVIRONMENT: ITestEnvironment; -describe("cmd-cli profiles create insecure", () => { - // Create the unique test environment - beforeAll(async () => { - TEST_ENVIRONMENT = await SetupTestEnvironment.createTestEnv({ - cliHomeEnvVar: "CMD_CLI_CLI_HOME", - testName: "cmd_profiles_create_insecure" - }); - }); - - it("should create a profile with a field marked as secure in plain text if the cli does not mark keytar as a dependency", () => { - const response = runCliScript(__dirname + "/__scripts__/profiles/create_insecure_profile.sh", TEST_ENVIRONMENT.workingDir); - expect(response.stderr.toString()).toContain("command 'profiles create insecure' is deprecated"); - expect(response.stderr.toString()).toContain("command 'profiles list insecure' is deprecated"); - expect(response.stdout.toString()).toContain("not so secret info"); - expect(response.stdout.toString()).not.toContain("managed by"); - expect(response.status).toBe(0); - }); -}); diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/banana.config.json b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/banana.config.json new file mode 100644 index 0000000000..a731429402 --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/banana.config.json @@ -0,0 +1,20 @@ +{ + "profiles": { + "bananaProfName": { + "type": "banana", + "properties": { + "color": "NoColorVal", + "bananaDescription": "NoDescriptionVal", + "moldType": "NoMoldTypeVal", + "sweetness": "mild", + "ripe": false, + "sides": 0, + "names": ["NoNamesVal"] + } + }, + }, + "defaults": { + "banana": "bananaProfName" + }, + "autoStore": true +} \ No newline at end of file diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/banana_profile_and_specify_cli.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/banana_profile_and_specify_cli.sh index 874280e425..dc9f5f7a46 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/banana_profile_and_specify_cli.sh +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/banana_profile_and_specify_cli.sh @@ -1,25 +1,27 @@ -#!/bin/bash +#!/bin/sh -color=$1 -description=$2 -moldtype=$3 +profileColor=${1:?"First parm (profileColor) is required."} +profileDescription=${2:?"Second parm (profileDescription) is required."} +profileMoldType=${3:?"Third parm (profileMoldType) is required."} -cliColor=$4 -cliDescription=$5 -cliMoldType=$6 -# First create a banana profile -cmd-cli profiles create banana-profile "test_banana" --color "$color" --banana-description "$description" --mold-type "$moldtype" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_banana profile of type banana failed!" 1>&2 - exit $CMDRC -fi +cliColor=${4:?"Fourth parm (cliColor) is required."} +cliDescription=${5:?"Fifth parm (cliDescription) is required."} +cliMoldType=${6:?"Sixth parm (cliMoldType) is required."} +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# set desired properties in our config file +cp $myScriptDir/banana.config.json . +exitOnFailure "Failed to copy config file." $? + +sed -e "s/NoColorVal/$profileColor/" \ + -e "s/NoDescriptionVal/$profileDescription/" \ + -e "s/NoMoldTypeVal/$profileMoldType/" \ + < banana.config.json > cmd-cli.config.json +exitOnFailure "Failed to update config file." $? + +# show the property values that will be used cmd-cli profile mapping --color "$cliColor" --banana-description "$cliDescription" --mold-type "$cliMoldType" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Profile mapping command failed!" 1>&2 - exit $CMDRC -fi +exitOnFailure "The 'profile mapping' command failed." $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/banana_profile_and_specify_env.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/banana_profile_and_specify_env.sh index 66411bdf10..74a8433318 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/banana_profile_and_specify_env.sh +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/banana_profile_and_specify_env.sh @@ -1,25 +1,27 @@ -#!/bin/bash +#!/bin/sh -color=$1 -description=$2 -moldtype=$3 +profileColor=${1:?"First parm (profileColor) is required."} +profileDescription=${2:?"Second parm (profileDescription) is required."} +profileMoldType=${3:?"Third parm (profileMoldType) is required."} -cliColor=$4 -cliDescription=$5 -cliMoldType=$6 -# First create a banana profile -cmd-cli profiles create banana-profile "test_banana" --color "$color" --banana-description "$description" --mold-type "$moldtype" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_banana profile of type banana failed!" 1>&2 - exit $CMDRC -fi +envColor=${4:?"Fourth parm (envColor) is required."} +envDescription=${5:?"Fifth parm (envDescription) is required."} +envMoldType=${6:?"Sixth parm (envMoldType) is required."} -CMD_CLI_OPT_COLOR="$4" CMD_CLI_OPT_BANANA_DESCRIPTION="$5" CMD_CLI_OPT_MOLD_TYPE="$6" cmd-cli profile mapping -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Profile mapping command failed!" 1>&2 - exit $CMDRC -fi +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# set desired properties in our config file +cp $myScriptDir/banana.config.json . +exitOnFailure "Failed to copy config file." $? + +sed -e "s/NoColorVal/$profileColor/" \ + -e "s/NoDescriptionVal/$profileDescription/" \ + -e "s/NoMoldTypeVal/$profileMoldType/" \ + < banana.config.json > cmd-cli.config.json +exitOnFailure "Failed to update config file." $? + +# show the property values that will be used +CMD_CLI_OPT_COLOR="$envColor" CMD_CLI_OPT_BANANA_DESCRIPTION="$envDescription" CMD_CLI_OPT_MOLD_TYPE="$envMoldType" cmd-cli profile mapping +exitOnFailure "The 'profile mapping' command failed." $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/banana_profile_and_specify_env_and_cli.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/banana_profile_and_specify_env_and_cli.sh index ae000d93a6..058942b964 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/banana_profile_and_specify_env_and_cli.sh +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/banana_profile_and_specify_env_and_cli.sh @@ -1,25 +1,32 @@ -#!/bin/bash +#!/bin/sh -color=$1 -description=$2 -moldtype=$3 +profileColor=${1:?"First parm (profileColor) is required."} +profileDescription=${2:?"Second parm (profileDescription) is required."} +profileMoldType=${3:?"Third parm (profileMoldType) is required."} -cliColor=$7 -cliDescription=$8 -cliMoldType=$9 -# First create a banana profile -cmd-cli profiles create banana-profile "test_banana" --color "$color" --banana-description "$description" --mold-type "$moldtype" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_banana profile of type banana failed!" 1>&2 - exit $CMDRC -fi +envColor=${4:?"Fourth parm (envColor) is required."} +envDescription=${5:?"Fifth parm (envDescription) is required."} +envMoldType=${6:?"Sixth parm (envMoldType) is required."} -CMD_CLI_OPT_COLOR="$4" CMD_CLI_OPT_BANANA_DESCRIPTION="$5" CMD_CLI_OPT_MOLD_TYPE="$6" cmd-cli profile mapping --color "$cliColor" --banana-description "$cliDescription" --mold-type "$cliMoldType" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Profile mapping command failed!" 1>&2 - exit $CMDRC -fi +cliColor=${7:?"Seventh parm (cliColor) is required."} +cliDescription=${8:?"Eighth parm (cliDescription) is required."} +cliMoldType=${9:?"Nineth parm (cliMoldType) is required."} + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# set desired properties in our config file +cp $myScriptDir/banana.config.json . +exitOnFailure "Failed to copy config file." $? + +sed -e "s/NoColorVal/$profileColor/" \ + -e "s/NoDescriptionVal/$profileDescription/" \ + -e "s/NoMoldTypeVal/$profileMoldType/" \ + < banana.config.json > cmd-cli.config.json +exitOnFailure "Failed to update config file." $? + +# show the property values that will be used +CMD_CLI_OPT_COLOR="$envColor" CMD_CLI_OPT_BANANA_DESCRIPTION="$envDescription" CMD_CLI_OPT_MOLD_TYPE="$envMoldType" \ + cmd-cli profile mapping --color "$cliColor" --banana-description "$cliDescription" --mold-type "$cliMoldType" +exitOnFailure "The 'profile mapping' command failed." $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/base_and_kiwi.config.json b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/base_and_kiwi.config.json new file mode 100644 index 0000000000..cab203266e --- /dev/null +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/base_and_kiwi.config.json @@ -0,0 +1,22 @@ +{ + "profiles": { + "baseProfName": { + "type": "base", + "properties": { + "amount": NoBaseAmountVal, + "price": NoBasePriceVal + } + }, + "kiwiProfName": { + "type": "kiwi", + "properties": { + "amount": NoKiwiAmountVal + } + } + }, + "defaults": { + "base": "baseProfName", + "kiwi": "kiwiProfName" + }, + "autoStore": true +} \ No newline at end of file diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/base_and_kiwi_profile.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/base_and_kiwi_profile.sh index 81a7bc8bab..ce499eef37 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/base_and_kiwi_profile.sh +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/base_and_kiwi_profile.sh @@ -1,31 +1,23 @@ -#!/bin/bash +#!/bin/sh -baseAmount=$1 -basePrice=$2 -kiwiAmount=$3 +baseAmount=${1:?"First parm (baseAmount) is required."} +basePrice=${2:?"Second parm (basePrice) is required."} +kiwiAmount=${3:?"Third parm (kiwiAmount) is required."} -# First create a base profile -cmd-cli profiles create base-profile "test_base" --amount $baseAmount --price $basePrice -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_base profile of type base failed!" 1>&2 - exit $CMDRC -fi +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh -# Next create a kiwi profile -cmd-cli profiles create kiwi-profile "test_kiwi" --amount $kiwiAmount --dd -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_kiwi profile of type kiwi failed!" 1>&2 - exit $CMDRC -fi +# set desired properties in our config file +cp $myScriptDir/base_and_kiwi.config.json . +exitOnFailure "Failed to copy config file." $? +sed -e "s/NoBaseAmountVal/$baseAmount/" \ + -e "s/NoBasePriceVal/$basePrice/" \ + -e "s/NoKiwiAmountVal/$kiwiAmount/" \ + < base_and_kiwi.config.json > cmd-cli.config.json +exitOnFailure "Failed to update config file." $? + +# show the property values that will be used cmd-cli profile mapping-base -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Profile mapping command failed!" 1>&2 - exit $CMDRC -fi +exitOnFailure "The 'profile mapping' command failed." $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/create_insecure_profile.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/create_insecure_profile.sh deleted file mode 100644 index da85e0cad8..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/create_insecure_profile.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -cmd-cli profiles create insecure "test_insecure" --info "some info" --secret "not so secret info" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a profile of type 'insecure' failed!" 1>&2 - exit $CMDRC -fi - -cmd-cli profiles list insecure --sc \ No newline at end of file diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/create_some_profiles.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/create_some_profiles.sh deleted file mode 100644 index bb23d58ce9..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/create_some_profiles.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -# First create a banana profile -cmd-cli profiles create banana-profile "test_banana" --color "green" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_banana profile of type banana failed!" 1>&2 - exit $CMDRC -fi - -# Next create a strawberry profile with the same name as the banana profile -# This should cause the defaults of both types to be the same profile name -cmd-cli profiles create strawberry-profile "test_banana" --amount 1000 -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_banana profile of type strawberry failed!" 1>&2 - exit $CMDRC -fi - -# Next create a strawberry profile with the same name as the banana profile -cmd-cli profiles create strawberry-profile "test_strawberry" --amount 1000 -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_strawberry profile failed!" 1>&2 - exit $CMDRC -fi - -# Next create a kiwi profile with kiwiSecret not defined -cmd-cli profiles create kiwi-profile "test_kiwi" --amount 1000 -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_kiwi profile failed!" 1>&2 - exit $CMDRC -fi diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/list_profiles_of_type.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/list_profiles_of_type.sh deleted file mode 100644 index ef2f15619a..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/list_profiles_of_type.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -cmd-cli profiles list $1-profiles --show-contents -exit $? \ No newline at end of file diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/map_banana_to_options.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/map_banana_to_options.sh index 250c287730..afbb066e5e 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/map_banana_to_options.sh +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/map_banana_to_options.sh @@ -1,21 +1,23 @@ -#!/bin/bash +#!/bin/sh -color=$1 -description=$2 -moldtype=$3 -# First create a banana profile -cmd-cli profiles create banana-profile "test_banana" --color "$color" --banana-description "$description" --mold-type "$moldtype" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_banana profile of type banana failed!" 1>&2 - exit $CMDRC -fi +profileColor=${1:?"First parm (profileColor) is required."} +profileDescription=${2:?"Second parm (profileDescription) is required."} +profileMoldType=${3:?"Third parm (profileMoldType) is required."} +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# set desired properties in our config file +cp $myScriptDir/banana.config.json . +exitOnFailure "Failed to copy config file." $? + +sed -e "s/NoColorVal/$profileColor/" \ + -e "s/NoDescriptionVal/$profileDescription/" \ + -e "s/NoMoldTypeVal/$profileMoldType/" \ + < banana.config.json > cmd-cli.config.json +exitOnFailure "Failed to update config file." $? + +# show the property values that will be used cmd-cli profile mapping -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Profile mapping command failed!" 1>&2 - exit $CMDRC -fi +exitOnFailure "The 'profile mapping' command failed." $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/map_banana_to_positionals.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/map_banana_to_positionals.sh index fd49ad0234..60f783253c 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/map_banana_to_positionals.sh +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/map_banana_to_positionals.sh @@ -1,21 +1,22 @@ -#!/bin/bash +#!/bin/sh -color=$1 -description=$2 -moldtype=$3 -# First create a banana profile -cmd-cli profiles create banana-profile "test_banana" --color "$color" --banana-description "$description" --mold-type "$moldtype" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_banana profile of type banana failed!" 1>&2 - exit $CMDRC -fi +profileColor=${1:?"First parm (profileColor) is required."} +profileDescription=${2:?"Second parm (profileDescription) is required."} +profileMoldType=${3:?"Third parm (profileMoldType) is required."} + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# set desired properties in our config file +cp $myScriptDir/banana.config.json . +exitOnFailure "Failed to copy config file." $? + +sed -e "s/NoColorVal/$profileColor/" \ + -e "s/NoDescriptionVal/$profileDescription/" \ + -e "s/NoMoldTypeVal/$profileMoldType/" \ + < banana.config.json > cmd-cli.config.json +exitOnFailure "Failed to update config file." $? cmd-cli profile mapping-positional -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Profile mapping command failed!" 1>&2 - exit $CMDRC -fi +exitOnFailure "The 'profile mapping-positional' command failed." $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/name_type_specify.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/name_type_specify.sh index 22bae3af8f..763e21da98 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/name_type_specify.sh +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/name_type_specify.sh @@ -1,23 +1,25 @@ -#!/bin/bash +#!/bin/sh + +profileColor=${1:?"First parm (profileColor) is required."} +profileDescription=${2:?"Second parm (profileDescription) is required."} +profileMoldType=${3:?"Third parm (profileMoldType) is required."} +cliName=${4:?"Fourth parm (cliName) is required."} +cliType=${5:?"Fifth parm (cliType) is required."} + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# set desired properties in our config file +cp $myScriptDir/banana.config.json . +exitOnFailure "Failed to copy config file." $? + +sed -e "s/NoColorVal/$profileColor/" \ + -e "s/NoDescriptionVal/$profileDescription/" \ + -e "s/NoMoldTypeVal/$profileMoldType/" \ + < banana.config.json > cmd-cli.config.json +exitOnFailure "Failed to update config file." $? -color=$1 -description=$2 -moldtype=$3 -# First create a banana profile -cmd-cli profiles create banana-profile "test_banana" --color "$color" --banana-description "$description" --mold-type "$moldtype" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_banana profile of type banana failed!" 1>&2 - exit $CMDRC -fi - cliName=$4 -cliType=$5 # should print the name and type that are specified, not the profile name or type cmd-cli profile mapping-name-type "$cliName" --type "$cliType" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Profile mapping command failed!" 1>&2 - exit $CMDRC -fi \ No newline at end of file +exitOnFailure "The 'profile mapping-name-type' command failed." $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/name_type_undefined.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/name_type_undefined.sh index 82b1bd9c7b..dc016314f4 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/name_type_undefined.sh +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/name_type_undefined.sh @@ -1,21 +1,23 @@ -#!/bin/bash +#!/bin/sh + +profileColor=${1:?"First parm (profileColor) is required."} +profileDescription=${2:?"Second parm (profileDescription) is required."} +profileMoldType=${3:?"Third parm (profileMoldType) is required."} + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +# set desired properties in our config file +cp $myScriptDir/banana.config.json . +exitOnFailure "Failed to copy config file." $? + +sed -e "s/NoColorVal/$profileColor/" \ + -e "s/NoDescriptionVal/$profileDescription/" \ + -e "s/NoMoldTypeVal/$profileMoldType/" \ + < banana.config.json > cmd-cli.config.json +exitOnFailure "Failed to update config file." $? -color=$1 -description=$2 -moldtype=$3 -# First create a banana profile -cmd-cli profiles create banana-profile "test_banana" --color "$color" --banana-description "$description" --mold-type "$moldtype" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Creating a test_banana profile of type banana failed!" 1>&2 - exit $CMDRC -fi # should print name: undefined type: undefined, not the profile name or type cmd-cli profile mapping-name-type -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Profile mapping command failed!" 1>&2 - exit $CMDRC -fi \ No newline at end of file +exitOnFailure "The 'profile mapping-name-type' command failed." $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_for_array.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_for_array.sh index 96e1f69290..37ca311c3e 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_for_array.sh +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_for_array.sh @@ -1,13 +1,13 @@ -#!/bin/bash +#!/bin/sh -cliColor=$1 -cliDescription=$2 -cliMoldType=$3 +cliColor=${1:?"First parm (cliColor) is required."} +cliDescription=${2:?"Second parm (cliDescription) is required."} +cliMoldType=${3:?"Third parm (cliMoldType) is required."} +envNames=${4:?"Fourth parm (envNames) is required."} -CMD_CLI_OPT_NAMES="$4" cmd-cli profile mapping --color "$cliColor" --banana-description "$cliDescription" --mold-type "$cliMoldType" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Profile mapping command failed!" 1>&2 - exit $CMDRC -fi +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +CMD_CLI_OPT_NAMES="$envNames" cmd-cli profile mapping --color "$cliColor" --banana-description "$cliDescription" --mold-type "$cliMoldType" +exitOnFailure "The 'profile mapping' command failed." $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_for_boolean.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_for_boolean.sh index 7f234835ba..74f16677af 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_for_boolean.sh +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_for_boolean.sh @@ -1,13 +1,13 @@ -#!/bin/bash +#!/bin/sh -cliColor=$1 -cliDescription=$2 -cliMoldType=$3 +cliColor=${1:?"First parm (cliColor) is required."} +cliDescription=${2:?"Second parm (cliDescription) is required."} +cliMoldType=${3:?"Third parm (cliMoldType) is required."} +envRipe=${4:?"Fourth parm (envRipe) is required."} -CMD_CLI_OPT_RIPE=$4 cmd-cli profile mapping --color "$cliColor" --banana-description "$cliDescription" --mold-type "$cliMoldType" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Profile mapping command failed!" 1>&2 - exit $CMDRC -fi +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +CMD_CLI_OPT_RIPE=$envRipe cmd-cli profile mapping --color "$cliColor" --banana-description "$cliDescription" --mold-type "$cliMoldType" +exitOnFailure "The 'profile mapping' command failed." $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_for_number.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_for_number.sh index ab7258c438..1a82c3d3b8 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_for_number.sh +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_for_number.sh @@ -1,13 +1,13 @@ -#!/bin/bash +#!/bin/sh -cliColor=$1 -cliDescription=$2 -cliMoldType=$3 +cliColor=${1:?"First parm (cliColor) is required."} +cliDescription=${2:?"Second parm (cliDescription) is required."} +cliMoldType=${3:?"Third parm (cliMoldType) is required."} +envSides=${4:?"Fourth parm (envSides) is required."} -CMD_CLI_OPT_SIDES=$4 cmd-cli profile mapping --color "$cliColor" --banana-description "$cliDescription" --mold-type "$cliMoldType" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Profile mapping command failed!" 1>&2 - exit $CMDRC -fi +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +CMD_CLI_OPT_SIDES=$envSides cmd-cli profile mapping --color "$cliColor" --banana-description "$cliDescription" --mold-type "$cliMoldType" +exitOnFailure "The 'profile mapping' command failed." $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_for_positional.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_for_positional.sh index ef2b4c71f5..cdfd23f411 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_for_positional.sh +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_for_positional.sh @@ -1,9 +1,13 @@ -#!/bin/bash +#!/bin/sh -CMD_CLI_OPT_COLOR="$1" CMD_CLI_OPT_BANANA_DESCRIPTION="$2" CMD_CLI_OPT_MOLD_TYPE="$3" cmd-cli profile mapping-positional -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Profile mapping command failed!" 1>&2 - exit $CMDRC -fi +envColor=${1:?"First parm (envColor) is required."} +envDescription=${2:?"Second parm (envDescription) is required."} +envMoldType=${3:?"Third parm (envMoldType) is required."} + +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh + +CMD_CLI_OPT_COLOR="$envColor" CMD_CLI_OPT_BANANA_DESCRIPTION="$envDescription" CMD_CLI_OPT_MOLD_TYPE="$envMoldType" \ + cmd-cli profile mapping-positional +exitOnFailure "The 'profile mapping-positional' command failed." $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_sweetness.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_sweetness.sh index 9137cab837..6109b33546 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_sweetness.sh +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__scripts__/profiles/specify_env_sweetness.sh @@ -1,14 +1,13 @@ -#!/bin/bash +#!/bin/sh +cliColor=${1:?"First parm (cliColor) is required."} +cliDescription=${2:?"Second parm (cliDescription) is required."} +cliMoldType=${3:?"Third parm (cliMoldType) is required."} +envSweetness=${4:?"Fourth parm (envSweetness) is required."} -cliColor=$1 -cliDescription=$2 -cliMoldType=$3 +# include zowe-cli\__tests__\__scripts__\exitOnFailure function +myScriptDir=`dirname $0` +. $myScriptDir/../../../../../../../../../../../__tests__/__scripts__/exitOnFailure.sh -CMD_CLI_OPT_SWEETNESS="$4" cmd-cli profile mapping --color "$cliColor" --banana-description "$cliDescription" --mold-type "$cliMoldType" -CMDRC=$? -if [ $CMDRC -gt 0 ] -then - echo "Profile mapping command failed!" 1>&2 - exit $CMDRC -fi +CMD_CLI_OPT_SWEETNESS="$envSweetness" cmd-cli profile mapping --color "$cliColor" --banana-description "$cliDescription" --mold-type "$cliMoldType" +exitOnFailure "The 'profile mapping' command failed." $? diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__snapshots__/Cmd.cli.profiles.create.banana-profile.integration.test.ts.snap b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__snapshots__/Cmd.cli.profiles.create.banana-profile.integration.test.ts.snap deleted file mode 100644 index d45fa14349..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/profiles/__snapshots__/Cmd.cli.profiles.create.banana-profile.integration.test.ts.snap +++ /dev/null @@ -1,30 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`cmd-cli profiles create banana should create profiles and only list the type requested 1`] = ` -"- - name: test_banana (default) - contents: - color: green -" -`; - -exports[`cmd-cli profiles create banana should create profiles and only list the type requested 2`] = ` -"- - name: test_banana (default) - contents: - amount: 1000 -- - name: test_strawberry - contents: - amount: 1000 -" -`; - -exports[`cmd-cli profiles create banana should create profiles and only list the type requested 3`] = ` -"- - name: test_kiwi (default) - contents: - amount: 1000 - price: 1 -" -`; diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/read/Cmd.cli.read.profile.integration.test.ts b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/read/Cmd.cli.read.profile.integration.test.ts deleted file mode 100644 index 76eece4fde..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/read/Cmd.cli.read.profile.integration.test.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { runCliScript } from "../../../../../../src/TestUtil"; -import { ITestEnvironment } from "../../../../../../__src__/environment/doc/response/ITestEnvironment"; -import { SetupTestEnvironment } from "../../../../../../__src__/environment/SetupTestEnvironment"; -// Test Environment populated in the beforeAll(); -let TEST_ENVIRONMENT: ITestEnvironment; -describe("cmd-cli profiles read profiles", () => { - // Create the unique test environment - beforeAll(async () => { - TEST_ENVIRONMENT = await SetupTestEnvironment.createTestEnv({ - cliHomeEnvVar: "CMD_CLI_CLI_HOME", - testName: "cmd_read_profiles" - }); - }); - - it("should create a profile with a field marked as secure in plain text (no keytar) and be able to read the contents", () => { - const response = runCliScript(__dirname + "/__scripts__/profile/create_and_read.sh", TEST_ENVIRONMENT.workingDir); - expect(response.stderr.toString()).toContain("command 'profiles create insecure' is deprecated"); - expect(response.stdout.toString()).toContain("not so secret info"); - expect(response.stdout.toString()).not.toContain("managed by"); - expect(response.status).toBe(0); - }); -}); diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/read/__scripts__/profile/create_and_read.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/read/__scripts__/profile/create_and_read.sh deleted file mode 100644 index d142b03524..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/read/__scripts__/profile/create_and_read.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -set -e -OUTPUT=$(cmd-cli profiles create insecure "test_insecure" --info "some info" --secret "not so secret info") -cmd-cli read profile diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/root/Cmd.cli.root.integration.test.ts b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/root/Cmd.cli.root.integration.test.ts index 8f7c398c8e..9d54634a50 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/root/Cmd.cli.root.integration.test.ts +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/root/Cmd.cli.root.integration.test.ts @@ -42,15 +42,21 @@ describe("cmd-cli", () => { it("should flag an invalid group and give a close suggestion", async () => { const response = runCliScript(__dirname + "/__scripts__/invalid_command.sh", TEST_ENVIRONMENT.workingDir); expect(response.status).toBe(1); - expect(response.stdout.toString()).toMatchSnapshot(); - expect(response.stderr.toString()).toMatchSnapshot(); + expect(response.stdout.toString()).toContain('================ISSUING CMD WITH INVALID GROUP==============='); + expect(response.stderr.toString()).toContain('Command failed due to improper syntax'); + expect(response.stderr.toString()).toContain('Unknown group: NOT_REAL'); + expect(response.stderr.toString()).toContain('Did you mean: auth?'); + expect(response.stderr.toString()).toContain('Command entered: "NOT_REAL"'); + expect(response.stderr.toString()).toContain('Use "cmd-cli --help" to view groups, commands, and options.'); }); - it("should flag an invalid command and list valid commands", async () => { + it("should flag a valid command with invalid arguments", async () => { const response = runCliScript(__dirname + "/__scripts__/invalid_command2.sh", TEST_ENVIRONMENT.workingDir); expect(response.status).toBe(1); - expect(response.stderr.toString()).toContain( - "Available commands are \"banana-profile, strawberry-profile, kiwi-profile, insecure-profile, base-profile\""); + expect(response.stderr.toString()).toContain("Unknown argument: vegetable"); + expect(response.stderr.toString()).toContain("Command failed due to improper syntax"); + expect(response.stderr.toString()).toContain("Did you mean: auth login fruit?"); + expect(response.stderr.toString()).toContain('Command entered: "auth login vegetable"'); }); it("should display the version", async () => { diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/root/__scripts__/invalid_command2.sh b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/root/__scripts__/invalid_command2.sh index d963a61f76..75e9eeeb23 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/root/__scripts__/invalid_command2.sh +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/root/__scripts__/invalid_command2.sh @@ -1,5 +1,5 @@ #!/bin/bash echo "================ISSUING CMD WITH VALID GROUP AND INVALID CMD===============" -cmd-cli profiles cre abc +cmd-cli auth login vegetable exit $? \ No newline at end of file diff --git a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/root/__snapshots__/Cmd.cli.root.integration.test.ts.snap b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/root/__snapshots__/Cmd.cli.root.integration.test.ts.snap index 7287ebde76..669c13bad7 100644 --- a/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/root/__snapshots__/Cmd.cli.root.integration.test.ts.snap +++ b/packages/imperative/__tests__/__integration__/cmd/__tests__/integration/cli/root/__snapshots__/Cmd.cli.root.integration.test.ts.snap @@ -18,18 +18,16 @@ exports[`cmd-cli should display the help 1`] = ` GROUPS ------ - auth Connect to token-based authentication services - auto-format Invoke handlers to test auto-format - chained chained handler test commands - gen-help Commands to test help generator - invalid Invalid definitions - invoke Invoke handlers to test promise reject/fulfill - nested Test a complex structure - profile Validate profile mapping - profiles Create and manage configuration profiles. (deprecated) - read Read some profiles - respond Invoke handlers that will produce messages - validate Validate syntax checking + auth Connect to token-based authentication services + auto-format Invoke handlers to test auto-format + chained chained handler test commands + gen-help Commands to test help generator + invalid Invalid definitions + invoke Invoke handlers to test promise reject/fulfill + nested Test a complex structure + profile Validate profile mapping + respond Invoke handlers that will produce messages + validate Validate syntax checking OPTIONS ------- @@ -74,18 +72,16 @@ exports[`cmd-cli should display the help 1`] = ` GROUPS ------ - auth Connect to token-based authentication services - auto-format Invoke handlers to test auto-format - chained chained handler test commands - gen-help Commands to test help generator - invalid Invalid definitions - invoke Invoke handlers to test promise reject/fulfill - nested Test a complex structure - profile Validate profile mapping - profiles Create and manage configuration profiles. (deprecated) - read Read some profiles - respond Invoke handlers that will produce messages - validate Validate syntax checking + auth Connect to token-based authentication services + auto-format Invoke handlers to test auto-format + chained chained handler test commands + gen-help Commands to test help generator + invalid Invalid definitions + invoke Invoke handlers to test promise reject/fulfill + nested Test a complex structure + profile Validate profile mapping + respond Invoke handlers that will produce messages + validate Validate syntax checking OPTIONS ------- @@ -118,7 +114,7 @@ exports[`cmd-cli should display the help 1`] = ` \\"success\\": true, \\"exitCode\\": 0, \\"message\\": \\"\\", - \\"stdout\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n A test CLI for the 'cmd' imperative package\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n cmd-cli \\\\n\\\\n Where is one of the following:\\\\n\\\\n GROUPS\\\\n ------\\\\n\\\\n auth Connect to token-based authentication services \\\\n auto-format Invoke handlers to test auto-format \\\\n chained chained handler test commands \\\\n gen-help Commands to test help generator \\\\n invalid Invalid definitions \\\\n invoke Invoke handlers to test promise reject/fulfill \\\\n nested Test a complex structure \\\\n profile Validate profile mapping \\\\n profiles Create and manage configuration profiles. (deprecated)\\\\n read Read some profiles \\\\n respond Invoke handlers that will produce messages \\\\n validate Validate syntax checking \\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --version | -V (boolean)\\\\n\\\\n Display the current version of Cmd Package CLI\\\\n\\\\n --available-commands | --ac (boolean)\\\\n\\\\n Displays a list of available commands\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", + \\"stdout\\": \\"\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n A test CLI for the 'cmd' imperative package\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n cmd-cli \\\\n\\\\n Where is one of the following:\\\\n\\\\n GROUPS\\\\n ------\\\\n\\\\n auth Connect to token-based authentication services\\\\n auto-format Invoke handlers to test auto-format \\\\n chained chained handler test commands \\\\n gen-help Commands to test help generator \\\\n invalid Invalid definitions \\\\n invoke Invoke handlers to test promise reject/fulfill\\\\n nested Test a complex structure \\\\n profile Validate profile mapping \\\\n respond Invoke handlers that will produce messages \\\\n validate Validate syntax checking \\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --version | -V (boolean)\\\\n\\\\n Display the current version of Cmd Package CLI\\\\n\\\\n --available-commands | --ac (boolean)\\\\n\\\\n Displays a list of available commands\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n\\", \\"stderr\\": \\"\\", \\"data\\": {} }" @@ -126,23 +122,8 @@ exports[`cmd-cli should display the help 1`] = ` exports[`cmd-cli should display the version 1`] = ` "================ISSUING VERSION=============== -0.0.0 -" -`; - -exports[`cmd-cli should flag an invalid group and give a close suggestion 1`] = ` -"================ISSUING CMD WITH INVALID GROUP=============== -" -`; - -exports[`cmd-cli should flag an invalid group and give a close suggestion 2`] = ` -"Command Error: -Command failed due to improper syntax -Unknown group: NOT_REAL -Did you mean: auth? - -Command entered: \\"NOT_REAL\\" -Use \\"cmd-cli --help\\" to view groups, commands, and options. +CLI Version: 0.0.0 +Zowe Release Version: V99 " `; @@ -150,11 +131,11 @@ exports[`cmd-cli should show a list of available commands 1`] = ` "================ISSUING HELP NO OPTIONS=============== cmd-cli auth login fruit - Log in to fruit authentication service + Log in to fruit authentication service. cmd-cli auth logout fruit - Log out of fruit authentication service + Log out of fruit authentication service. cmd-cli auto-format cmd-output @@ -213,11 +194,6 @@ cmd-cli invalid no-handler This will never get invoked. No handler specified on this definition. -cmd-cli invalid profile-spec - - Command handler attempts to load a profile that wasn't specified on the command - definition - cmd-cli invoke exit-143 Test handler that exits with status code 143 @@ -277,136 +253,6 @@ cmd-cli profile mapping-positional Tests Imperative's profile to CLI mapping capabilities. -cmd-cli profiles create banana-profile - - Banana Profile - -cmd-cli profiles create base-profile - - Fruit Profile - -cmd-cli profiles create insecure-profile - - Test Secured Fields - -cmd-cli profiles create kiwi-profile - - Kiwi Profile - -cmd-cli profiles create strawberry-profile - - Strawberry Profile - -cmd-cli profiles delete banana-profile - - Delete a banana profile. You must specify a profile name to be deleted. To find - a list of available profiles for deletion, issue the profiles list command. By - default, you will be prompted to confirm the profile removal. - -cmd-cli profiles delete base-profile - - Delete a base profile. You must specify a profile name to be deleted. To find a - list of available profiles for deletion, issue the profiles list command. By - default, you will be prompted to confirm the profile removal. - -cmd-cli profiles delete insecure-profile - - Delete a insecure profile. You must specify a profile name to be deleted. To - find a list of available profiles for deletion, issue the profiles list command. - By default, you will be prompted to confirm the profile removal. - -cmd-cli profiles delete kiwi-profile - - Delete a kiwi profile. You must specify a profile name to be deleted. To find a - list of available profiles for deletion, issue the profiles list command. By - default, you will be prompted to confirm the profile removal. - -cmd-cli profiles delete strawberry-profile - - Delete a strawberry profile. You must specify a profile name to be deleted. To - find a list of available profiles for deletion, issue the profiles list command. - By default, you will be prompted to confirm the profile removal. - -cmd-cli profiles list banana-profiles - - Banana Profile - -cmd-cli profiles list base-profiles - - Fruit Profile - -cmd-cli profiles list insecure-profiles - - Test Secured Fields - -cmd-cli profiles list kiwi-profiles - - Kiwi Profile - -cmd-cli profiles list strawberry-profiles - - Strawberry Profile - -cmd-cli profiles set-default banana-profile - - The banana set default-profiles command allows you to set the default profiles - for this command group. When a banana command is issued and no profile override - options are specified, the default profiles for the command group are - automatically loaded for the command based on the commands profile requirements. - -cmd-cli profiles set-default base-profile - - The base set default-profiles command allows you to set the default profiles for - this command group. When a base command is issued and no profile override - options are specified, the default profiles for the command group are - automatically loaded for the command based on the commands profile requirements. - -cmd-cli profiles set-default insecure-profile - - The insecure set default-profiles command allows you to set the default profiles - for this command group. When a insecure command is issued and no profile - override options are specified, the default profiles for the command group are - automatically loaded for the command based on the commands profile requirements. - -cmd-cli profiles set-default kiwi-profile - - The kiwi set default-profiles command allows you to set the default profiles for - this command group. When a kiwi command is issued and no profile override - options are specified, the default profiles for the command group are - automatically loaded for the command based on the commands profile requirements. - -cmd-cli profiles set-default strawberry-profile - - The strawberry set default-profiles command allows you to set the default - profiles for this command group. When a strawberry command is issued and no - profile override options are specified, the default profiles for the command - group are automatically loaded for the command based on the commands profile - requirements. - -cmd-cli profiles update banana-profile - - Banana Profile - -cmd-cli profiles update base-profile - - Fruit Profile - -cmd-cli profiles update insecure-profile - - Test Secured Fields - -cmd-cli profiles update kiwi-profile - - Kiwi Profile - -cmd-cli profiles update strawberry-profile - - Strawberry Profile - -cmd-cli read profile - - Read some profiles - cmd-cli respond with-data-array Formulates a string array object to pass back when response format JSON is diff --git a/packages/imperative/__tests__/__integration__/cmd/package.json b/packages/imperative/__tests__/__integration__/cmd/package.json index 08b7fe6699..2c3d184688 100644 --- a/packages/imperative/__tests__/__integration__/cmd/package.json +++ b/packages/imperative/__tests__/__integration__/cmd/package.json @@ -1,6 +1,7 @@ { "name": "cmd-sample-cli", "version": "0.0.0", + "zoweVersion": "V99", "description": "Command Sample CLI", "license": "EPL-2.0", "repository": "", diff --git a/packages/imperative/__tests__/__integration__/cmd/src/cli/auth/FruitAuthHandler.ts b/packages/imperative/__tests__/__integration__/cmd/src/cli/auth/FruitAuthHandler.ts index 1f9f883831..a939a52377 100644 --- a/packages/imperative/__tests__/__integration__/cmd/src/cli/auth/FruitAuthHandler.ts +++ b/packages/imperative/__tests__/__integration__/cmd/src/cli/auth/FruitAuthHandler.ts @@ -9,7 +9,8 @@ * */ -import { BaseAuthHandler, AbstractSession, ICommandArguments, ISession, SessConstants } from "../../../../../../lib"; +import { BaseAuthHandler, AbstractSession, CredentialManagerFactory, ICommandArguments, ISession, SessConstants +} from "../../../../../../lib"; /** * This class is used by the auth command handlers as the base class for their implementation. @@ -52,6 +53,13 @@ export default class ApimlAuthHandler extends BaseAuthHandler { * @returns {Promise} The response from the auth service containing a token */ protected async doLogin(session: AbstractSession) { + await CredentialManagerFactory.initialize({ + service: null, + Manager: null, + displayName: null, + invalidOnFailure: null + }); + if (session.ISession.user) { return `${session.ISession.user}:${session.ISession.password}@fakeToken`; } else { diff --git a/packages/imperative/__tests__/__integration__/cmd/src/cli/invalid/Invalid.definition.ts b/packages/imperative/__tests__/__integration__/cmd/src/cli/invalid/Invalid.definition.ts index d6ca7fef31..6c0fa036ba 100644 --- a/packages/imperative/__tests__/__integration__/cmd/src/cli/invalid/Invalid.definition.ts +++ b/packages/imperative/__tests__/__integration__/cmd/src/cli/invalid/Invalid.definition.ts @@ -12,15 +12,13 @@ import { ICommandDefinition } from "../../../../../../lib/index"; import { NoHandlerDefinition } from "./no-handler/NoHandler.definition"; import { InvalidHandlerDefinition } from "./invalid-handler/InvalidHandler.definition"; -import { ProfileSpecDefinition } from "./profile-spec/ProfileSpec.definition"; export const definition: ICommandDefinition = { name: "invalid", description: "Attempt to invoke commands that have poorly coded definitions.", summary: "Invalid definitions", type: "group", - children: [NoHandlerDefinition, InvalidHandlerDefinition, - ProfileSpecDefinition] + children: [NoHandlerDefinition, InvalidHandlerDefinition] }; module.exports = definition; diff --git a/packages/imperative/__tests__/__integration__/cmd/src/cli/invalid/profile-spec/ProfileSpec.definition.ts b/packages/imperative/__tests__/__integration__/cmd/src/cli/invalid/profile-spec/ProfileSpec.definition.ts deleted file mode 100644 index a14f67bb4c..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/src/cli/invalid/profile-spec/ProfileSpec.definition.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandDefinition } from "../../../../../../../lib"; - - -export const ProfileSpecDefinition: ICommandDefinition = { - name: "profile-spec", - aliases: ["ao"], - description: "Command handler attempts to load a profile that wasn't specified on the command definition", - type: "command", - handler: __dirname + "/ProfileSpec.handler" -}; diff --git a/packages/imperative/__tests__/__integration__/cmd/src/cli/invalid/profile-spec/ProfileSpec.handler.ts b/packages/imperative/__tests__/__integration__/cmd/src/cli/invalid/profile-spec/ProfileSpec.handler.ts deleted file mode 100644 index 750248d6c4..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/src/cli/invalid/profile-spec/ProfileSpec.handler.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandHandler, IHandlerParameters } from "../../../../../../../lib"; - -export default class ProfileSpecHandler implements ICommandHandler { - public async process(params: IHandlerParameters): Promise { - // eslint-disable-next-line deprecation/deprecation - params.profiles.get("blah"); - } -} diff --git a/packages/imperative/__tests__/__integration__/cmd/src/cli/read/Read.definition.ts b/packages/imperative/__tests__/__integration__/cmd/src/cli/read/Read.definition.ts deleted file mode 100644 index d10a2b8121..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/src/cli/read/Read.definition.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandDefinition } from "../../../../../../lib"; -import { ProfileCommand } from "./profile/Profile.definition"; - -export const definition: ICommandDefinition = { - name: "read", - description: "Read some profiles", - summary: "Read some profiles", - type: "group", - children: [ProfileCommand], -}; - -module.exports = definition; diff --git a/packages/imperative/__tests__/__integration__/cmd/src/cli/read/profile/Profile.definition.ts b/packages/imperative/__tests__/__integration__/cmd/src/cli/read/profile/Profile.definition.ts deleted file mode 100644 index f8a0337eef..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/src/cli/read/profile/Profile.definition.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandDefinition } from "../../../../../../../lib"; - -export const ProfileCommand: ICommandDefinition = { - name: "profile", - description: "Read some profiles", - summary: "Read some profiles", - type: "command", - handler: __dirname + "/Profile.handler", - profile: { - required: ["insecure"] - } -}; diff --git a/packages/imperative/__tests__/__integration__/cmd/src/cli/read/profile/Profile.handler.ts b/packages/imperative/__tests__/__integration__/cmd/src/cli/read/profile/Profile.handler.ts deleted file mode 100644 index 18da0fe758..0000000000 --- a/packages/imperative/__tests__/__integration__/cmd/src/cli/read/profile/Profile.handler.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IHandlerParameters, ICommandHandler, TextUtils } from "../../../../../../../lib/index"; - -export default class FirstGroupCommandOneHandler implements ICommandHandler { - public async process(params: IHandlerParameters): Promise { - // eslint-disable-next-line deprecation/deprecation - const prof = params.profiles.get("insecure"); - params.response.console.log(TextUtils.prettyJson(prof)); - } -} diff --git a/packages/imperative/__tests__/__integration__/hello_world/__tests__/__snapshots__/HelloWorldCli.integration.test.ts.snap b/packages/imperative/__tests__/__integration__/hello_world/__tests__/__snapshots__/HelloWorldCli.integration.test.ts.snap index b0a0a3688b..6f25772045 100644 --- a/packages/imperative/__tests__/__integration__/hello_world/__tests__/__snapshots__/HelloWorldCli.integration.test.ts.snap +++ b/packages/imperative/__tests__/__integration__/hello_world/__tests__/__snapshots__/HelloWorldCli.integration.test.ts.snap @@ -49,7 +49,8 @@ exports[`Hello World should print help if the option is specified 1`] = ` `; exports[`Hello World should print version if the option is specified 1`] = ` -"0.0.0 +"CLI Version: 0.0.0 +Zowe Release Version: V99 " `; diff --git a/packages/imperative/__tests__/__integration__/hello_world/package.json b/packages/imperative/__tests__/__integration__/hello_world/package.json index 66c623db7a..849e84bc98 100644 --- a/packages/imperative/__tests__/__integration__/hello_world/package.json +++ b/packages/imperative/__tests__/__integration__/hello_world/package.json @@ -1,6 +1,7 @@ { "name": "hello-world-cli", "version": "0.0.0", + "zoweVersion": "V99", "description": "Hello World Sample CLI", "license": "EPL 2.0", "repository": "", diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/api/env/EnvironmentalVariableSettings.integration.test.ts b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/api/env/EnvironmentalVariableSettings.integration.test.ts index cccf8207b3..a5e1730b23 100644 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/api/env/EnvironmentalVariableSettings.integration.test.ts +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/api/env/EnvironmentalVariableSettings.integration.test.ts @@ -15,19 +15,10 @@ import { EnvironmentalVariableSettings, Imperative } from "../../../../../../../src"; describe("environmental variable integration", () => { - // eslint-disable-next-line deprecation/deprecation - const mainModule = process.mainModule; - beforeEach(() => { - // eslint-disable-next-line deprecation/deprecation - (process.mainModule as any) = { - filename: __filename - }; - }); - - afterEach(() => { - // eslint-disable-next-line deprecation/deprecation - process.mainModule = mainModule; + afterAll(() => { + process.env.IMP_INTEGRATION_TESTING_IMPERATIVE_LOG_LEVEL = ""; + process.env.IMP_INTEGRATION_TESTING_APP_LOG_LEVEL = ""; }); it ("should be able to extract the values for the environment variables", () => { @@ -64,5 +55,8 @@ describe("environmental variable integration", () => { // TODO: I think this is a defect - level is defined as type "string", but returns an object expect(Imperative.api.imperativeLogger.level as any).toBe("ERROR"); expect(Imperative.api.appLogger.level as any).toBe("WARN"); + + process.env[vars.appLogLevel.key] = ""; + process.env[vars.imperativeLogLevel.key] = ""; }); }); diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/cli.imperative-test-cli.integration.subtest.ts b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/cli.imperative-test-cli.integration.subtest.ts new file mode 100644 index 0000000000..3ecf113291 --- /dev/null +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/cli.imperative-test-cli.integration.subtest.ts @@ -0,0 +1,30 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +// These tests require access to the same values on the keyring, therefore they cannot run in parallel +// The test order is important - some tests depend on other tests not running first - do not change it +/* eslint-disable max-len */ + +describe("Imperative Test CLI Secure Tests", () => { + // require("./auth/imperative.test.cli.auth.login.fruit.integration.subtest"); + // require("./auth/imperative.test.cli.auth.logout.fruit.integration.subtest"); + require("./config/auto-init/imperative.test.cli.config.auto-init.fruit.integration.subtest"); + require("./config/convert-profiles/cli.imperative-test-cli.config.convert-profiles.integration.subtest"); + require("./config/edit/cli.imperative-test-cli.config.edit.integration.subtest"); + require("./config/import/cli.imperative-test-cli.config.import.integration.subtest"); + require("./config/init/cli.imperative-test-cli.config.init.integration.subtest"); + require("./config/list/cli.imperative-test-cli.config.list.integration.subtest"); + require("./config/profiles/cli.imperative-test-cli.config.profiles.integration.subtest"); + require("./config/secure/cli.imperative-test-cli.config.secure.integration.subtest"); + require("./config/set/cli.imperative-test-cli.config.set.integration.subtest"); + require("./test/cli.imperative-test-cli.test.config-auto-store.integration.subtest"); + require("./test/cli.imperative-test-cli.test.config-override.integration.subtest"); +}); diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/expectedObjects.ts b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/expectedObjects.ts index 39a1965232..9f231d37c9 100644 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/expectedObjects.ts +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/expectedObjects.ts @@ -147,6 +147,14 @@ export const expectedSchemaObject = { tokenValue: { type: "string", description: "Fruit token value" + }, + certFile: { + type: "existingLocalFile", + description: "Fruit certificate file" + }, + certKeyFile: { + type: "existingLocalFile", + description: "Fruit certificate key file" } } }, @@ -188,7 +196,7 @@ export const expectedSchemaObject = { } }; -export const expectedConfigObject: IConfig = { +export const expectedGlobalConfigObject: IConfig = { $schema: "./imperative-test-cli.schema.json", profiles: { secured: { @@ -198,7 +206,7 @@ export const expectedConfigObject: IConfig = { }, secure: [] }, - base: { + global_base: { type: "base", properties: {}, secure: ["secret"] @@ -206,12 +214,12 @@ export const expectedConfigObject: IConfig = { }, defaults: { secured: "secured", - base: "base" + base: "global_base" }, autoStore: true }; -export const expectedUserConfigObject: IConfig = { +export const expectedGlobalUserConfigObject: IConfig = { $schema: "./imperative-test-cli.schema.json", profiles: { secured: { @@ -219,10 +227,51 @@ export const expectedUserConfigObject: IConfig = { properties: {}, secure: [] }, - base: { + global_base: { + type: "base", + properties: {}, + secure: ["secret"] + }, + }, + defaults: {}, + autoStore: true +}; + +export const expectedProjectConfigObject: IConfig = { + $schema: "./imperative-test-cli.schema.json", + profiles: { + secured: { + type: "secured", + properties: { + info: "" + }, + secure: [] + }, + project_base: { type: "base", properties: {}, + secure: ["secret"] + }, + }, + defaults: { + secured: "secured", + base: "project_base" + }, + autoStore: true +}; + +export const expectedProjectUserConfigObject: IConfig = { + $schema: "./imperative-test-cli.schema.json", + profiles: { + secured: { + type: "secured", + properties: {}, secure: [] + }, + project_base: { + type: "base", + properties: {}, + secure: ["secret"] } }, defaults: {}, diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/plugins/plugins.json b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/plugins/plugins.json new file mode 100644 index 0000000000..e17d2382f9 --- /dev/null +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/plugins/plugins.json @@ -0,0 +1,22 @@ +{ + "@zowe/secure-credential-store-for-zowe-cli": { + "package": "@zowe/secure-credential-store-for-zowe-cli@zowe-v1-lts", + "registry": "https://registry.npmjs.org/", + "version": "4.1.12" + }, + "@zowe/cics-for-zowe-cli": { + "package": "@zowe/cics-for-zowe-cli@zowe-v1-lts", + "registry": "https://registry.npmjs.org/", + "version": "4.0.11" + }, + "@broadcom/jclcheck-for-zowe-cli": { + "package": "@broadcom/jclcheck-for-zowe-cli@zowe-v1-lts", + "registry": "https://registry.npmjs.org/", + "version": "1.1.2" + }, + "@broadcom/endevor-for-zowe-cli": { + "package": "@broadcom/endevor-for-zowe-cli@zowe-v1-lts", + "registry": "https://registry.npmjs.org/", + "version": "5.7.6" + } +} diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/profiles_secured_and_base/base/base_meta.yaml b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/profiles_secured_and_base/base/base_meta.yaml new file mode 100644 index 0000000000..40afa6c96b --- /dev/null +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/profiles_secured_and_base/base/base_meta.yaml @@ -0,0 +1,157 @@ +defaultProfile: test +configuration: + type: base + schema: + type: object + title: 'Secure Profile' + description: 'Secure Profile' + properties: + info: + type: string + optionDefinition: + name: info + description: 'The info the keep in the profile.' + type: string + group: Options + aliases: [] + secret: + type: string + secure: true + includeInTemplate: true + optionDefinition: + name: secret + description: 'The secret info the keep in the profile.' + type: string + group: Options + aliases: [] + host: + type: string + optionDefinition: + name: host + description: 'Fruit host' + type: string + group: Options + aliases: [] + port: + type: number + optionDefinition: + name: port + description: 'Fruit port' + type: number + group: Options + aliases: [] + user: + type: string + optionDefinition: + name: user + description: 'Fruit username' + type: string + group: Options + aliases: [] + secure: true + password: + type: string + optionDefinition: + name: password + description: 'Fruit password' + type: string + group: Options + aliases: [] + secure: true + tokenType: + type: string + optionDefinition: + name: token-type + description: 'Fruit token type' + type: string + group: Options + aliases: [] + tokenValue: + type: string + optionDefinition: + name: token-value + description: 'Fruit token value' + type: string + group: Options + aliases: [] + secure: true + authConfig: + - + serviceName: fruit + handler: /home/stduser/repos/zowe-cli/packages/imperative/__tests__/__integration__/imperative/lib/cli/auth/FruitAuthHandler + login: + options: + - + name: info + description: 'The info the keep in the profile.' + type: string + group: Options + aliases: [] + - + name: secret + description: 'The secret info the keep in the profile.' + type: string + group: Options + aliases: [] + - + name: host + description: 'Fruit host' + type: string + group: Options + aliases: [] + - + name: port + description: 'Fruit port' + type: number + group: Options + aliases: [] + - + name: user + description: 'Fruit username' + type: string + group: Options + aliases: [] + - + name: password + description: 'Fruit password' + type: string + group: Options + aliases: [] + logout: + options: + - + name: info + description: 'The info the keep in the profile.' + type: string + group: Options + aliases: [] + - + name: secret + description: 'The secret info the keep in the profile.' + type: string + group: Options + aliases: [] + - + name: host + description: 'Fruit host' + type: string + group: Options + aliases: [] + - + name: port + description: 'Fruit port' + type: number + group: Options + aliases: [] + - + name: token-type + description: 'Fruit token type' + type: string + group: Options + aliases: [] + - + name: token-value + description: 'Fruit token value' + type: string + group: Options + aliases: [] diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/profiles_secured_and_base/base/test.yaml b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/profiles_secured_and_base/base/test.yaml new file mode 100644 index 0000000000..b5263a8558 --- /dev/null +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/profiles_secured_and_base/base/test.yaml @@ -0,0 +1 @@ +host: example.com diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/profiles_secured_and_base/secured/secured_meta.yaml b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/profiles_secured_and_base/secured/secured_meta.yaml new file mode 100644 index 0000000000..d3cc574273 --- /dev/null +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/profiles_secured_and_base/secured/secured_meta.yaml @@ -0,0 +1,24 @@ +defaultProfile: test +configuration: + type: secured + schema: + type: object + title: 'Test Secured Fields' + description: 'Test Secured Fields' + properties: + info: + type: string + includeInTemplate: true + optionDefinition: + name: info + description: 'The info the keep in the profile.' + type: string + required: true + secret: + type: string + secure: true + optionDefinition: + name: secret + description: 'The secret info the keep in the profile.' + type: string + required: true diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/profiles_secured_and_base/secured/test.yaml b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/profiles_secured_and_base/secured/test.yaml new file mode 100644 index 0000000000..2e7290be7d --- /dev/null +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/profiles_secured_and_base/secured/test.yaml @@ -0,0 +1,2 @@ +info: hello +secret: 'managed by Imperative Package Test CLI' diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/auto-init/imperative.test.cli.config.auto-init.fruit.integration.subtest.ts b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/auto-init/imperative.test.cli.config.auto-init.fruit.integration.subtest.ts index 4e9ad9c6fe..ffbf94c9ec 100644 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/auto-init/imperative.test.cli.config.auto-init.fruit.integration.subtest.ts +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/auto-init/imperative.test.cli.config.auto-init.fruit.integration.subtest.ts @@ -118,7 +118,7 @@ describe("cmd-cli config auto-init", () => { expect(response.status).toBe(0); expect(glob.sync("*.json", { cwd: TEST_ENVIRONMENT.workingDir })) - .toEqual(["imperative-test-cli.config.json", "imperative-test-cli.schema.json"]); + .toEqual(["extenders.json", "imperative-test-cli.config.json", "imperative-test-cli.schema.json"]); const configJson: IConfig = jsonfile.readFileSync(TEST_ENVIRONMENT.workingDir + "/imperative-test-cli.config.json"); expect(configJson.profiles.base_fruit).toBeDefined(); expect(configJson.profiles.base_fruit.properties.tokenValue).toBeUndefined(); @@ -135,7 +135,7 @@ describe("cmd-cli config auto-init", () => { expect(response.status).toBe(0); expect(glob.sync("*.json", { cwd: TEST_ENVIRONMENT.workingDir })) - .toEqual(["imperative-test-cli.config.user.json", "imperative-test-cli.schema.json"]); + .toEqual(["extenders.json", "imperative-test-cli.config.user.json", "imperative-test-cli.schema.json"]); const configJson: IConfig = jsonfile.readFileSync(TEST_ENVIRONMENT.workingDir + "/imperative-test-cli.config.user.json"); expect(configJson.profiles.base_fruit).toBeDefined(); expect(configJson.profiles.base_fruit.properties.tokenValue).toBeUndefined(); diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/__scripts__/convert_profiles.sh b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/__scripts__/convert_profiles.sh index 8aab0170ef..6d4f3a228d 100644 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/__scripts__/convert_profiles.sh +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/__scripts__/convert_profiles.sh @@ -1,4 +1,4 @@ #!/bin/bash -echo $1 | imperative-test-cli config convert-profiles +imperative-test-cli config convert-profiles exit $? diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/__scripts__/create_profiles_secured_and_base.sh b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/__scripts__/create_profiles_secured_and_base.sh deleted file mode 100644 index c9428deec7..0000000000 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/__scripts__/create_profiles_secured_and_base.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -imperative-test-cli profiles create secured test --info hello --secret world -if [ $? -gt 0 ] -then - exit $? -fi - -imperative-test-cli profiles create base test --host example.com -exit $? diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/__scripts__/delete_profiles.sh b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/__scripts__/delete_profiles.sh new file mode 100644 index 0000000000..baad2b2114 --- /dev/null +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/__scripts__/delete_profiles.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +# Delete all available profiles, but leave the profile type definitions +for profile in profiles/base/test.yaml profiles/secured/test.yaml profiles/v1profile/myv1profile.yaml; do + if [ -e $profile ]; then + rm $profile + fi +done diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/__scripts__/delete_profiles_secured_and_base.sh b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/__scripts__/delete_profiles_secured_and_base.sh deleted file mode 100644 index db09b2ab45..0000000000 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/__scripts__/delete_profiles_secured_and_base.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -imperative-test-cli profiles delete secured test -if [ $? -gt 0 ] -then - exit $? -fi - -imperative-test-cli profiles delete base test -if [ $? -gt 0 ] -then - exit $? -fi - -imperative-test-cli profiles delete v1profile myv1profile -exit $? diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/__scripts__/delete_profiles_secured_and_base_noerr.sh b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/__scripts__/delete_profiles_secured_and_base_noerr.sh deleted file mode 100644 index 8985bbed3f..0000000000 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/__scripts__/delete_profiles_secured_and_base_noerr.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -imperative-test-cli profiles delete secured test || true - -imperative-test-cli profiles delete base test || true - -imperative-test-cli profiles delete v1profile myv1profile || true diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/cli.imperative-test-cli.config.convert-profiles.integration.subtest.ts b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/cli.imperative-test-cli.config.convert-profiles.integration.subtest.ts index c849cc4f34..8025b02006 100644 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/cli.imperative-test-cli.config.convert-profiles.integration.subtest.ts +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/convert-profiles/cli.imperative-test-cli.config.convert-profiles.integration.subtest.ts @@ -12,7 +12,7 @@ import * as fs from "fs"; import * as fsExtra from "fs-extra"; import * as path from "path"; -import { keyring as keytar } from "@zowe/secrets-for-zowe-sdk"; +import { keyring } from "@zowe/secrets-for-zowe-sdk"; import { ITestEnvironment } from "../../../../../../../__src__/environment/doc/response/ITestEnvironment"; import { SetupTestEnvironment } from "../../../../../../../__src__/environment/SetupTestEnvironment"; import { runCliScript } from "../../../../../../../src/TestUtil"; @@ -29,90 +29,103 @@ describe("imperative-test-cli config convert-profiles", () => { cliHomeEnvVar: "IMPERATIVE_TEST_CLI_CLI_HOME", testName: "imperative_test_cli_test_config_convert_profiles_command" }); - configJsonPath = path.join(process.env.IMPERATIVE_TEST_CLI_CLI_HOME, "imperative-test-cli.config.json"); + configJsonPath = path.join(process.env.IMPERATIVE_TEST_CLI_CLI_HOME as string, "imperative-test-cli.config.json"); + // jest.spyOn(EventOperator, "getZoweProcessor").mockReturnValue({emitZoweEvent: jest.fn()} as any); }); beforeEach(() => { - runCliScript(__dirname + "/__scripts__/create_profiles_secured_and_base.sh", TEST_ENVIRONMENT.workingDir); + fsExtra.copySync(__dirname + "/../../config/__resources__/profiles_secured_and_base", TEST_ENVIRONMENT.workingDir + "/profiles"); + fsExtra.copySync(__dirname + "/../../config/__resources__/plugins", TEST_ENVIRONMENT.workingDir + "/plugins"); }); afterEach(() => { - runCliScript(__dirname + "/__scripts__/delete_profiles_secured_and_base_noerr.sh", TEST_ENVIRONMENT.workingDir); + const response = runCliScript(__dirname + "/__scripts__/delete_profiles.sh", TEST_ENVIRONMENT.workingDir); + expect(response.stdout.toString()).toEqual(""); + expect(response.stderr.toString()).toEqual(""); + if (fs.existsSync(configJsonPath)) { fs.unlinkSync(configJsonPath); } fsExtra.removeSync(TEST_ENVIRONMENT.workingDir + "/profiles-old"); }); - describe("success scenarios", () => { - it("should display the help", () => { - const response = runCliScript(__dirname + "/../__scripts__/get_help.sh", TEST_ENVIRONMENT.workingDir, ["convert-profiles"]); - expect(response.status).toBe(0); - expect(response.stdout.toString()).toContain("Convert v1 profiles to a global imperative-test-cli.config.json file."); - expect(response.stderr.toString()).toEqual(""); - }); + it("should display the help", () => { + const response = runCliScript(__dirname + "/../__scripts__/get_help.sh", TEST_ENVIRONMENT.workingDir, ["convert-profiles"]); + expect(response.status).toBe(0); + expect(response.stdout.toString()).toContain("Convert v1 profiles to a global imperative-test-cli.config.json file."); + expect(response.stderr.toString()).toEqual(""); + }); - it("should convert profiles to team config", async () => { - const response = runCliScript(__dirname + "/__scripts__/convert_profiles.sh", TEST_ENVIRONMENT.workingDir, ["y"]); - expect(response.status).toBe(0); - expect(response.stdout.toString()).toContain("Detected 2 old profile(s) to convert"); - expect(response.stdout.toString()).toContain("Your new profiles have been saved"); - expect(response.stdout.toString()).toContain("Your old profiles have been moved"); - expect(response.stderr.toString()).toEqual(""); - - // Check contents of config JSON - const configJson = JSON.parse(fs.readFileSync(configJsonPath, "utf-8")); - expect(configJson).toMatchObject({ - profiles: { - secured_test: { - type: "secured", - properties: { - info: "hello" - }, - secure: ["secret"] - }, - base_test: { - type: "base", - properties: { - host: "example.com" - }, - secure: [] + it("should convert profiles to team config and keep old profiles", async () => { + // set a value in the secure vault that would have been created for the V1 secured profile + await keyring.setPassword("imperative-test-cli", "secured_test_secret", + Buffer.from('"world"').toString("base64") + ); + + const response = runCliScript(__dirname + "/__scripts__/convert_profiles.sh", TEST_ENVIRONMENT.workingDir); + expect(response.stdout.toString()).toContain("Your old V1 profiles have been moved"); + expect(response.stdout.toString()).toContain("Delete them by re-running this operation and requesting deletion"); + expect(response.stdout.toString()).toContain("Your new profiles have been saved"); + expect(response.stdout.toString()).toContain("To change your configuration, update that file in your text editor"); + expect(response.stderr.toString()).toEqual(""); + expect(response.status).toBe(0); + + // Check contents of config JSON + const configJson = JSON.parse(fs.readFileSync(configJsonPath, "utf-8")); + expect(configJson).toMatchObject({ + profiles: { + secured_test: { + type: "secured", + properties: { + info: "hello" }, + secure: ["secret"] }, - defaults: { - secured: "secured_test", - base: "base_test" + base_test: { + type: "base", + properties: { + host: "example.com" + }, + secure: [] }, - autoStore: true - }); - - // Check secure credentials stored in vault - const securedValue = await keytar.getPassword("imperative-test-cli", "secure_config_props"); - const secureConfigProps = JSON.parse(Buffer.from(securedValue, "base64").toString()); - expect(secureConfigProps).toMatchObject({ - [configJsonPath]: { - "profiles.secured_test.properties.secret": "world" - } - }); + }, + defaults: { + secured: "secured_test", + base: "base_test" + }, + autoStore: true + }); - // Ensure that profiles directory was renamed - const cliHomeDirContents = fs.readdirSync(process.env.IMPERATIVE_TEST_CLI_CLI_HOME); - expect(cliHomeDirContents.includes("profiles")).toBe(false); - expect(cliHomeDirContents.includes("profiles-old")).toBe(true); + // Check secure credentials stored in vault + const securedValue = await keyring.getPassword("imperative-test-cli", "secure_config_props"); + const secureConfigProps = JSON.parse(Buffer.from(securedValue as string, "base64").toString()); + expect(secureConfigProps).toMatchObject({ + [configJsonPath]: { + "profiles.secured_test.properties.secret": "world" + } }); + + // Ensure that profiles directory was renamed + const cliHomeDirContents = fs.readdirSync(process.env.IMPERATIVE_TEST_CLI_CLI_HOME as string); + expect(cliHomeDirContents.includes("profiles")).toBe(false); + expect(cliHomeDirContents.includes("profiles-old")).toBe(true); }); it("should convert v1 profile property names to v2 names", async () => { // we don't want the profiles created by beforeEach(). We only want an old profile. - runCliScript(__dirname + "/__scripts__/delete_profiles_secured_and_base_noerr.sh", TEST_ENVIRONMENT.workingDir); + let response = runCliScript(__dirname + "/__scripts__/delete_profiles.sh", TEST_ENVIRONMENT.workingDir); + expect(response.stdout.toString()).toEqual(""); + expect(response.stderr.toString()).toEqual(""); + fsExtra.copySync(__dirname + "/../../config/__resources__/profiles_with_v1_names", TEST_ENVIRONMENT.workingDir + "/profiles"); - const response = runCliScript(__dirname + "/__scripts__/convert_profiles.sh", TEST_ENVIRONMENT.workingDir, ["y"]); - expect(response.status).toBe(0); - expect(response.stdout.toString()).toContain("Detected 1 old profile(s) to convert"); + response = runCliScript(__dirname + "/__scripts__/convert_profiles.sh", TEST_ENVIRONMENT.workingDir); + expect(response.stdout.toString()).toContain("Your old V1 profiles have been moved"); + expect(response.stdout.toString()).toContain("Delete them by re-running this operation and requesting deletion"); expect(response.stdout.toString()).toContain("Your new profiles have been saved"); - expect(response.stdout.toString()).toContain("Your old profiles have been moved"); + expect(response.stdout.toString()).toContain("To change your configuration, update that file in your text editor"); expect(response.stderr.toString()).toEqual(""); + expect(response.status).toBe(0); // Check contents of config JSON const configJson = JSON.parse(fs.readFileSync(configJsonPath, "utf-8")); @@ -134,35 +147,39 @@ describe("imperative-test-cli config convert-profiles", () => { }); // Ensure that profiles directory was renamed - const cliHomeDirContents = fs.readdirSync(process.env.IMPERATIVE_TEST_CLI_CLI_HOME); + const cliHomeDirContents = fs.readdirSync(process.env.IMPERATIVE_TEST_CLI_CLI_HOME as string); expect(cliHomeDirContents.includes("profiles")).toBe(false); expect(cliHomeDirContents.includes("profiles-old")).toBe(true); }); - describe("failure scenarios", () => { - it("should not convert profiles if prompt is rejected", () => { - const response = runCliScript(__dirname + "/__scripts__/convert_profiles.sh", TEST_ENVIRONMENT.workingDir, ["n"]); - expect(response.status).toBe(0); - expect(response.stdout.toString()).toContain("Detected 2 old profile(s) to convert"); - expect(response.stdout.toString()).not.toContain("Your new profiles have been saved"); - expect(response.stdout.toString()).not.toContain("Your old profiles have been moved"); - expect(response.stderr.toString()).toEqual(""); - expect(fs.existsSync(configJsonPath)).toBe(false); - }); - it("should not delete profiles if prompt is rejected", () => { - runCliScript(__dirname + "/__scripts__/delete_profiles_secured_and_base.sh", TEST_ENVIRONMENT.workingDir); - - const response = runCliScript(__dirname + "/__scripts__/convert_profiles_delete.sh", TEST_ENVIRONMENT.workingDir, ["n"]); - expect(response.status).toBe(0); - expect(response.stdout.toString()).toContain("No old profiles were found"); - expect(response.stdout.toString()).toContain("Are you sure you want to delete your v1 profiles?"); - expect(response.stdout.toString()).not.toContain("Your new profiles have been saved"); - expect(response.stdout.toString()).not.toContain("Your old profiles have been moved"); - expect(response.stdout.toString()).not.toContain("Deleting the profiles directory"); - expect(response.stderr.toString()).not.toContain("Failed to delete the profiles directory"); - expect(response.stderr.toString()).not.toContain("Deleting secure value for"); - expect(response.stderr.toString()).not.toContain("Keytar or the credential vault are unavailable"); - expect(fs.existsSync(configJsonPath)).toBe(false); - }); + it("should delete profiles if deletion prompt is accepted", () => { + const response = runCliScript(__dirname + "/__scripts__/convert_profiles_delete.sh", TEST_ENVIRONMENT.workingDir, ["y"]); + expect(response.stdout.toString()).toContain("Do you want to delete your V1 profiles now [y/N]:"); + expect(response.stdout.toString()).toContain("Your new profiles have been saved"); + expect(response.stdout.toString()).toContain("To change your configuration, update that file in your text editor"); + expect(response.stdout.toString()).toContain("Deleted the old profiles directory"); + expect(response.stderr.toString()).toEqual(""); + expect(response.status).toBe(0); + + // Ensure that profiles directory was deleted + const cliHomeDirContents = fs.readdirSync(process.env.IMPERATIVE_TEST_CLI_CLI_HOME as string); + expect(cliHomeDirContents.includes("profiles")).toBe(false); + expect(cliHomeDirContents.includes("profiles-old")).toBe(false); + }); + + it("should keep profiles if deletion prompt is rejected", () => { + const response = runCliScript(__dirname + "/__scripts__/convert_profiles_delete.sh", TEST_ENVIRONMENT.workingDir, ["n"]); + expect(response.stdout.toString()).toContain("Do you want to delete your V1 profiles now [y/N]:"); + expect(response.stdout.toString()).toContain("Your old V1 profiles have been moved"); + expect(response.stdout.toString()).toContain("Delete them by re-running this operation and requesting deletion"); + expect(response.stdout.toString()).toContain("Your new profiles have been saved"); + expect(response.stdout.toString()).toContain("To change your configuration, update that file in your text editor"); + expect(response.stderr.toString()).toEqual(""); + expect(response.status).toBe(0); + + // Ensure that profiles-old directory was kept + const cliHomeDirContents = fs.readdirSync(process.env.IMPERATIVE_TEST_CLI_CLI_HOME as string); + expect(cliHomeDirContents.includes("profiles")).toBe(false); + expect(cliHomeDirContents.includes("profiles-old")).toBe(true); }); }); diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/edit/cli.imperative-test-cli.config.edit.integration.test.ts b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/edit/cli.imperative-test-cli.config.edit.integration.subtest.ts similarity index 98% rename from packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/edit/cli.imperative-test-cli.config.edit.integration.test.ts rename to packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/edit/cli.imperative-test-cli.config.edit.integration.subtest.ts index 83622aa440..af8b4342e5 100644 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/edit/cli.imperative-test-cli.config.edit.integration.test.ts +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/edit/cli.imperative-test-cli.config.edit.integration.subtest.ts @@ -51,7 +51,7 @@ describe("imperative-test-cli config convert-profiles", () => { it("should open config file in editor specified by environment variable", async () => { const response = runCliScript(__dirname + "/__scripts__/edit_config.sh", path.join(TEST_ENVIRONMENT.workingDir, "test"), [], { // Use "cat" in place of editor to print out the config file - IMPERATIVE_TEST_CLI_EDITOR: "cat", + IMPERATIVE_TEST_CLI_OPT_EDITOR: "cat", // Pretend to have SSH connection so isGuiAvailable returns false SSH_CONNECTION: "fake" }); diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/import/__snapshots__/cli.imperative-test-cli.config.import.integration.test.ts.snap b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/import/__snapshots__/cli.imperative-test-cli.config.import.integration.test.ts.snap deleted file mode 100644 index 015d0c0d8e..0000000000 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/import/__snapshots__/cli.imperative-test-cli.config.import.integration.test.ts.snap +++ /dev/null @@ -1,17 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`imperative-test-cli config import failure scenarios should fail to import if location is not specified 1`] = ` -" -Syntax Error: -Missing Positional Argument: location -Argument Description: File path or URL to import from. - -Example: - - - Import config from local file on disk: - - $ imperative-test-cli config import ~/Downloads/zowe.config.json - -Use \\"imperative-test-cli config import --help\\" to view command description, usage, and options. -" -`; diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/import/cli.imperative-test-cli.config.import.integration.test.ts b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/import/cli.imperative-test-cli.config.import.integration.subtest.ts similarity index 100% rename from packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/import/cli.imperative-test-cli.config.import.integration.test.ts rename to packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/import/cli.imperative-test-cli.config.import.integration.subtest.ts diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/init/cli.imperative-test-cli.config.init.integration.subtest.ts b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/init/cli.imperative-test-cli.config.init.integration.subtest.ts index 2927259cab..1ee04363eb 100644 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/init/cli.imperative-test-cli.config.init.integration.subtest.ts +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/init/cli.imperative-test-cli.config.init.integration.subtest.ts @@ -12,15 +12,26 @@ import { ITestEnvironment } from "../../../../../../../__src__/environment/doc/response/ITestEnvironment"; import { SetupTestEnvironment } from "../../../../../../../__src__/environment/SetupTestEnvironment"; import { runCliScript } from "../../../../../../../src/TestUtil"; -import { expectedSchemaObject, expectedConfigObject, expectedUserConfigObject } from "../__resources__/expectedObjects"; +import { + expectedSchemaObject, + expectedGlobalConfigObject, expectedGlobalUserConfigObject, + expectedProjectConfigObject, expectedProjectUserConfigObject +} from "../__resources__/expectedObjects"; import * as fs from "fs"; import * as path from "path"; - +import * as lodash from "lodash"; // Test Environment populated in the beforeAll(); let TEST_ENVIRONMENT: ITestEnvironment; describe("imperative-test-cli config init", () => { + // config-init creates user base profiles with an empty secure array + const expectedGlobalUserJson = lodash.cloneDeep(expectedGlobalUserConfigObject); + expectedGlobalUserJson.profiles.global_base.secure = []; + + const expectedProjectUserJson = lodash.cloneDeep(expectedProjectUserConfigObject); + expectedProjectUserJson.profiles.project_base.secure = []; + // Create the test environment beforeAll(async () => { TEST_ENVIRONMENT = await SetupTestEnvironment.createTestEnv({ @@ -51,132 +62,102 @@ describe("imperative-test-cli config init", () => { it("should initialize a project config", () => { const response = runCliScript(__dirname + "/__scripts__/init_config.sh", TEST_ENVIRONMENT.workingDir, ["--prompt false"]); - const expectedConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.config.json"); + const expectedProjectConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.config.json"); const expectedSchemaLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.schema.json"); expect(response.output.toString()).toContain(`Saved config template to`); - expect(response.output.toString()).toContain(expectedConfigLocation); - expect(fs.existsSync(expectedConfigLocation)).toEqual(true); - expect(fs.existsSync(expectedSchemaLocation)).toEqual(true); - expect(JSON.parse(fs.readFileSync(expectedConfigLocation).toString())).toEqual(expectedConfigObject); + expect(response.output.toString()).toContain(expectedProjectConfigLocation); + expect(fs.existsSync(expectedProjectConfigLocation)).toEqual(true); + expect(fs.existsSync(expectedProjectConfigLocation)).toEqual(true); + expect(JSON.parse(fs.readFileSync(expectedProjectConfigLocation).toString())).toEqual(expectedProjectConfigObject); expect(JSON.parse(fs.readFileSync(expectedSchemaLocation).toString())).toEqual(expectedSchemaObject); }); - it("should initialize a user project config", () => { + it("should initialize a project user config", () => { const response = runCliScript(__dirname + "/__scripts__/init_config.sh", TEST_ENVIRONMENT.workingDir, ["--user-config --prompt false"]); - const expectedConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.config.user.json"); + const expectedProjectUserConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.config.user.json"); const expectedSchemaLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.schema.json"); expect(response.output.toString()).toContain(`Saved config template to`); - expect(response.output.toString()).toContain(expectedConfigLocation); - expect(fs.existsSync(expectedConfigLocation)).toEqual(true); + expect(response.output.toString()).toContain(expectedProjectUserConfigLocation); + expect(fs.existsSync(expectedProjectUserConfigLocation)).toEqual(true); expect(fs.existsSync(expectedSchemaLocation)).toEqual(true); - expect(JSON.parse(fs.readFileSync(expectedConfigLocation).toString())).toEqual(expectedUserConfigObject); + expect(JSON.parse(fs.readFileSync(expectedProjectUserConfigLocation).toString())).toEqual(expectedProjectUserJson); expect(JSON.parse(fs.readFileSync(expectedSchemaLocation).toString())).toEqual(expectedSchemaObject); }); it("should initialize a global config", () => { const response = runCliScript(__dirname + "/__scripts__/init_config.sh", TEST_ENVIRONMENT.workingDir, ["--global-config --prompt false"]); - const expectedConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.json"); + const expectedGlobalConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.json"); const expectedSchemaLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.schema.json"); expect(response.output.toString()).toContain(`Saved config template to`); - expect(response.output.toString()).toContain(expectedConfigLocation); - expect(fs.existsSync(expectedConfigLocation)).toEqual(true); + expect(response.output.toString()).toContain(expectedGlobalConfigLocation); + expect(fs.existsSync(expectedGlobalConfigLocation)).toEqual(true); expect(fs.existsSync(expectedSchemaLocation)).toEqual(true); - expect(JSON.parse(fs.readFileSync(expectedConfigLocation).toString())).toEqual(expectedConfigObject); + expect(JSON.parse(fs.readFileSync(expectedGlobalConfigLocation).toString())).toEqual(expectedGlobalConfigObject); expect(JSON.parse(fs.readFileSync(expectedSchemaLocation).toString())).toEqual(expectedSchemaObject); }); it("should initialize a user global config", () => { const response = runCliScript(__dirname + "/__scripts__/init_config.sh", TEST_ENVIRONMENT.workingDir, ["--global-config --user-config --prompt false"]); - const expectedConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.user.json"); + const expectedGlobalUserConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.user.json"); const expectedSchemaLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.schema.json"); expect(response.output.toString()).toContain(`Saved config template to`); - expect(response.output.toString()).toContain(expectedConfigLocation); - expect(fs.existsSync(expectedConfigLocation)).toEqual(true); - expect(fs.existsSync(expectedSchemaLocation)).toEqual(true); - expect(JSON.parse(fs.readFileSync(expectedConfigLocation).toString())).toEqual(expectedUserConfigObject); + expect(response.output.toString()).toContain(expectedGlobalUserConfigLocation); + expect(fs.existsSync(expectedGlobalUserConfigLocation)).toEqual(true); + expect(fs.existsSync(expectedGlobalUserConfigLocation)).toEqual(true); + expect(JSON.parse(fs.readFileSync(expectedGlobalUserConfigLocation).toString())).toEqual(expectedGlobalUserJson); expect(JSON.parse(fs.readFileSync(expectedSchemaLocation).toString())).toEqual(expectedSchemaObject); }); it("should initialize a project config with prompting", () => { const response = runCliScript(__dirname + "/__scripts__/init_config_prompt.sh", TEST_ENVIRONMENT.workingDir, [""]); - const expectedConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.config.json"); + const expectedProjectConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.config.json"); const expectedSchemaLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.schema.json"); expect(response.output.toString()).not.toContain("Unable to securely save credentials"); expect(response.output.toString()).toContain(`Saved config template to`); - expect(response.output.toString()).toContain(expectedConfigLocation); - expect(fs.existsSync(expectedConfigLocation)).toEqual(true); + expect(response.output.toString()).toContain(expectedProjectConfigLocation); + expect(fs.existsSync(expectedProjectConfigLocation)).toEqual(true); expect(fs.existsSync(expectedSchemaLocation)).toEqual(true); - expect(JSON.parse(fs.readFileSync(expectedConfigLocation).toString())).toEqual(expectedConfigObject); + expect(JSON.parse(fs.readFileSync(expectedProjectConfigLocation).toString())).toEqual(expectedProjectConfigObject); expect(JSON.parse(fs.readFileSync(expectedSchemaLocation).toString())).toEqual(expectedSchemaObject); }); - it("should initialize a user project config with prompting", () => { + it("should initialize a project user config with prompting", () => { const response = runCliScript(__dirname + "/__scripts__/init_config_prompt.sh", TEST_ENVIRONMENT.workingDir, ["--user-config"]); - const expectedConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.config.user.json"); + const expectedProjectUserConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.config.user.json"); const expectedSchemaLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.schema.json"); expect(response.output.toString()).not.toContain("Unable to securely save credentials"); expect(response.output.toString()).toContain(`Saved config template to`); - expect(response.output.toString()).toContain(expectedConfigLocation); - expect(fs.existsSync(expectedConfigLocation)).toEqual(true); + expect(response.output.toString()).toContain(expectedProjectUserConfigLocation); + expect(fs.existsSync(expectedProjectUserConfigLocation)).toEqual(true); expect(fs.existsSync(expectedSchemaLocation)).toEqual(true); - expect(JSON.parse(fs.readFileSync(expectedConfigLocation).toString())).toEqual(expectedUserConfigObject); + expect(JSON.parse(fs.readFileSync(expectedProjectUserConfigLocation).toString())).toEqual(expectedProjectUserJson); expect(JSON.parse(fs.readFileSync(expectedSchemaLocation).toString())).toEqual(expectedSchemaObject); }); it("should initialize a global config with prompting", () => { const response = runCliScript(__dirname + "/__scripts__/init_config_prompt.sh", TEST_ENVIRONMENT.workingDir, ["--global-config"]); - const expectedConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.json"); + const expectedGlobalConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.json"); const expectedSchemaLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.schema.json"); expect(response.output.toString()).not.toContain("Unable to securely save credentials"); expect(response.output.toString()).toContain(`Saved config template to`); - expect(response.output.toString()).toContain(expectedConfigLocation); - expect(fs.existsSync(expectedConfigLocation)).toEqual(true); + expect(response.output.toString()).toContain(expectedGlobalConfigLocation); + expect(fs.existsSync(expectedGlobalConfigLocation)).toEqual(true); expect(fs.existsSync(expectedSchemaLocation)).toEqual(true); - expect(JSON.parse(fs.readFileSync(expectedConfigLocation).toString())).toEqual(expectedConfigObject); + expect(JSON.parse(fs.readFileSync(expectedGlobalConfigLocation).toString())).toEqual(expectedGlobalConfigObject); expect(JSON.parse(fs.readFileSync(expectedSchemaLocation).toString())).toEqual(expectedSchemaObject); }); it("should initialize a user global config with prompting", () => { const response = runCliScript(__dirname + "/__scripts__/init_config_prompt.sh", TEST_ENVIRONMENT.workingDir, ["--global-config --user-config"]); - const expectedConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.user.json"); + const expectedGlobalUserConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.user.json"); const expectedSchemaLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.schema.json"); expect(response.output.toString()).not.toContain("Unable to securely save credentials"); expect(response.output.toString()).toContain(`Saved config template to`); - expect(response.output.toString()).toContain(expectedConfigLocation); - expect(fs.existsSync(expectedConfigLocation)).toEqual(true); + expect(response.output.toString()).toContain(expectedGlobalUserConfigLocation); + expect(fs.existsSync(expectedGlobalUserConfigLocation)).toEqual(true); expect(fs.existsSync(expectedSchemaLocation)).toEqual(true); - expect(JSON.parse(fs.readFileSync(expectedConfigLocation).toString())).toEqual(expectedUserConfigObject); + expect(JSON.parse(fs.readFileSync(expectedGlobalUserConfigLocation).toString())).toEqual(expectedGlobalUserJson); expect(JSON.parse(fs.readFileSync(expectedSchemaLocation).toString())).toEqual(expectedSchemaObject); }); - // eslint-disable-next-line jest/no-commented-out-tests - // it("should create a profile of a specified name", () => { - // const response = runCliScript(__dirname + "/__scripts__/init_config.sh", - // TEST_ENVIRONMENT.workingDir, ["--profile lpar.service --prompt false"]); - // const expectedConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.json"); - // const expectedSchemaLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.schema.json"); - // const expectedConfigObject: IConfig = { - // $schema: "./imperative-test-cli.schema.json", - // profiles: { - // lpar: { - // properties: {}, - // profiles: { - // service: { - // properties: {} - // } - // } - // } - // }, - // defaults: {}, - // secure: [] - // }; - // expect(response.output.toString()).toContain(`Saved config template to`); - // expect(response.output.toString()).toContain(expectedConfigLocation); - // expect(fs.existsSync(expectedConfigLocation)).toEqual(true); - // expect(fs.existsSync(expectedSchemaLocation)).toEqual(true); - // expect(JSON.parse(fs.readFileSync(expectedConfigLocation).toString())).toEqual(expectedConfigObject); - // expect(JSON.parse(fs.readFileSync(expectedSchemaLocation).toString())).toEqual(expectedSchemaObject); - // runCliScript(__dirname + "/../__scripts__/delete_configs.sh", TEST_ENVIRONMENT.workingDir, - // ["imperative-test-cli.config.json imperative-test-cli.schema.json"]); - // }); }); diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/list/__snapshots__/cli.imperative-test-cli.config.list.integration.test.ts.snap b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/list/__snapshots__/cli.imperative-test-cli.config.list.integration.test.ts.snap deleted file mode 100644 index 6fe1aa04a1..0000000000 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/list/__snapshots__/cli.imperative-test-cli.config.list.integration.test.ts.snap +++ /dev/null @@ -1,70 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`imperative-test-cli config list should list the configuration 1`] = ` -"profiles: - secured: - type: secured - properties: - info: - secure: - (empty array) - base: - type: base - properties: - secure: - - secret -defaults: - secured: secured - base: base -autoStore: true -" -`; - -exports[`imperative-test-cli config list should list the configuration without showing secure values 1`] = ` -"profiles: - secured: - type: secured - properties: - info: - secure: - (empty array) - base: - type: base - properties: - secret: (secure value) - secure: - - secret -defaults: - secured: secured - base: base -autoStore: true -" -`; - -exports[`imperative-test-cli config list should list the defaults configuration property 1`] = ` -"secured: secured -base: base -" -`; - -exports[`imperative-test-cli config list should list the profiles configuration property 1`] = ` -"secured: - type: secured - properties: - info: - secure: - (empty array) -base: - type: base - properties: - secure: - - secret -" -`; - -exports[`imperative-test-cli config list should list the root level property names only 1`] = ` -"profiles -defaults -autoStore -" -`; diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/list/cli.imperative-test-cli.config.list.integration.test.ts b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/list/cli.imperative-test-cli.config.list.integration.subtest.ts similarity index 74% rename from packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/list/cli.imperative-test-cli.config.list.integration.test.ts rename to packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/list/cli.imperative-test-cli.config.list.integration.subtest.ts index 2ffbcb386c..538d952fc4 100644 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/list/cli.imperative-test-cli.config.list.integration.test.ts +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/list/cli.imperative-test-cli.config.list.integration.subtest.ts @@ -12,18 +12,21 @@ import { ITestEnvironment } from "../../../../../../../__src__/environment/doc/response/ITestEnvironment"; import { SetupTestEnvironment } from "../../../../../../../__src__/environment/SetupTestEnvironment"; import { runCliScript } from "../../../../../../../src/TestUtil"; -import { expectedConfigObject } from "../__resources__/expectedObjects"; +import { + expectedGlobalConfigObject, expectedGlobalUserConfigObject, + expectedProjectConfigObject, expectedProjectUserConfigObject +} from "../__resources__/expectedObjects"; import * as path from "path"; -import * as lodash from "lodash"; // Test Environment populated in the beforeAll(); let TEST_ENVIRONMENT: ITestEnvironment; describe("imperative-test-cli config list", () => { - let expectedGlobalProjectConfigLocation: string; + let expectedGlobalConfigLocation: string; let expectedGlobalUserConfigLocation: string; let expectedProjectConfigLocation: string; - let expectedUserConfigLocation: string; + let expectedProjectUserConfigLocation: string; + // Create the test environment beforeAll(async () => { TEST_ENVIRONMENT = await SetupTestEnvironment.createTestEnv({ @@ -36,14 +39,15 @@ describe("imperative-test-cli config list", () => { runCliScript(__dirname + "/../init/__scripts__/init_config.sh", TEST_ENVIRONMENT.workingDir, ["--user-config --global-config --prompt false"]); expectedGlobalUserConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.user.json"); - expectedGlobalProjectConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.json"); - expectedUserConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.config.user.json"); + expectedGlobalConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.json"); + expectedProjectUserConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.config.user.json"); expectedProjectConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.config.json"); }); afterAll(() => { runCliScript(__dirname + "/../__scripts__/delete_configs.sh", TEST_ENVIRONMENT.workingDir, ["-rf imperative-test-cli.config.user.json imperative-test-cli.config.json test imperative-test-cli.schema.json"]); }); + it("should display the help", () => { const response = runCliScript(__dirname + "/../__scripts__/get_help.sh", TEST_ENVIRONMENT.workingDir, ["list"]); @@ -69,7 +73,12 @@ describe("imperative-test-cli config list", () => { const expectedResponse = { data: { profiles: { - base: { + project_base: { + type: "base", + properties: {}, + secure: ["secret"] + }, + global_base: { properties: {}, type: "base", secure: ["secret"] @@ -84,7 +93,7 @@ describe("imperative-test-cli config list", () => { }, defaults: { secured: "secured", - base: "base" + base: "project_base" }, autoStore: true } @@ -97,8 +106,8 @@ describe("imperative-test-cli config list", () => { it("should list the configurations based on location", () => { const response = runCliScript(__dirname + "/__scripts__/list_config.sh", TEST_ENVIRONMENT.workingDir, ["--locations"]); expect(response.stdout.toString()).toContain(expectedProjectConfigLocation); - expect(response.stdout.toString()).toContain(expectedUserConfigLocation); - expect(response.stdout.toString()).toContain(expectedGlobalProjectConfigLocation); + expect(response.stdout.toString()).toContain(expectedProjectUserConfigLocation); + expect(response.stdout.toString()).toContain(expectedGlobalConfigLocation); expect(response.stdout.toString()).toContain(expectedGlobalUserConfigLocation); expect(response.stdout.toString()).toContain("defaults:"); expect(response.stdout.toString()).toContain("profiles:"); @@ -113,37 +122,28 @@ describe("imperative-test-cli config list", () => { it("should list the configurations based on location in RFJ", () => { const response = runCliScript(__dirname + "/__scripts__/list_config.sh", TEST_ENVIRONMENT.workingDir, ["--locations --rfj"]); const parsedResponse = JSON.parse(response.stdout.toString()); - const expectedUserConfig = { - $schema: "./imperative-test-cli.schema.json", - profiles: { - secured: { - properties: {}, - type: "secured", - secure: [] as string[] - }, - base: { - properties: {}, - type: "base", - secure: [] as string[] - } - }, - defaults: {}, - autoStore: true - }; - const expectedProjectConfig = lodash.cloneDeep(expectedConfigObject); + const expectedResponse = { data: {} as any }; - expectedResponse.data[expectedUserConfigLocation] = expectedUserConfig; - expectedResponse.data[expectedGlobalUserConfigLocation] = expectedUserConfig; - expectedResponse.data[expectedGlobalProjectConfigLocation] = expectedProjectConfig; - expectedResponse.data[expectedProjectConfigLocation] = expectedProjectConfig; + + // config-init of a user config creates no entries in the properties object or in the secure array. + // So, empty the secure arrays in the user configs. + expectedResponse.data[expectedProjectUserConfigLocation] = expectedProjectUserConfigObject; + expectedResponse.data[expectedProjectUserConfigLocation].profiles.project_base.secure = []; + + expectedResponse.data[expectedGlobalUserConfigLocation] = expectedGlobalUserConfigObject; + expectedResponse.data[expectedGlobalUserConfigLocation].profiles.global_base.secure = []; + + expectedResponse.data[expectedProjectConfigLocation] = expectedProjectConfigObject; + expectedResponse.data[expectedGlobalConfigLocation] = expectedGlobalConfigObject; + expect(parsedResponse.success).toEqual(true); expect(parsedResponse.stderr).toEqual(""); expect(parsedResponse.exitCode).toEqual(0); expect(parsedResponse.data).toEqual(expectedResponse.data); }); - it("should list the root level property names only", () => { + it("should list the root level property names only 1", () => { const response = runCliScript(__dirname + "/__scripts__/list_config.sh", TEST_ENVIRONMENT.workingDir, ["--root"]); expect(response.stdout.toString()).toMatchSnapshot(); expect(response.stdout.toString()).toContain("defaults"); @@ -151,11 +151,28 @@ describe("imperative-test-cli config list", () => { expect(response.stderr.toString()).toEqual(""); expect(response.error).toBeFalsy(); }); - it("should get a list of config file paths", () => { + it("should list the root level property names only 2", () => { + const response = runCliScript(__dirname + "/__scripts__/list_config.sh", TEST_ENVIRONMENT.workingDir, ["--name-only"]); + expect(response.stdout.toString()).toMatchSnapshot(); + expect(response.stdout.toString()).toContain("defaults"); + expect(response.stdout.toString()).toContain("profiles"); + expect(response.stderr.toString()).toEqual(""); + expect(response.error).toBeFalsy(); + }); + it("should get a list of config file paths 1", () => { const response = runCliScript(__dirname + "/__scripts__/list_config.sh", TEST_ENVIRONMENT.workingDir, ["--locations --root"]); expect(response.stdout.toString()).toContain(expectedProjectConfigLocation); - expect(response.stdout.toString()).toContain(expectedUserConfigLocation); - expect(response.stdout.toString()).toContain(expectedGlobalProjectConfigLocation); + expect(response.stdout.toString()).toContain(expectedProjectUserConfigLocation); + expect(response.stdout.toString()).toContain(expectedGlobalConfigLocation); + expect(response.stdout.toString()).toContain(expectedGlobalUserConfigLocation); + expect(response.stderr.toString()).toEqual(""); + expect(response.error).toBeFalsy(); + }); + it("should get a list of config file paths 2", () => { + const response = runCliScript(__dirname + "/__scripts__/list_config.sh", TEST_ENVIRONMENT.workingDir, ["--locations --name-only"]); + expect(response.stdout.toString()).toContain(expectedProjectConfigLocation); + expect(response.stdout.toString()).toContain(expectedProjectUserConfigLocation); + expect(response.stdout.toString()).toContain(expectedGlobalConfigLocation); expect(response.stdout.toString()).toContain(expectedGlobalUserConfigLocation); expect(response.stderr.toString()).toEqual(""); expect(response.error).toBeFalsy(); @@ -176,12 +193,14 @@ describe("imperative-test-cli config list", () => { const response = runCliScript(__dirname + "/__scripts__/list_config.sh", TEST_ENVIRONMENT.workingDir, ["defaults"]); expect(response.stdout.toString()).toMatchSnapshot(); expect(response.stdout.toString()).toContain("secured: secured"); - expect(response.stdout.toString()).toContain("base: base"); + expect(response.stdout.toString()).toContain("base: project_base"); expect(response.stderr.toString()).toEqual(""); expect(response.error).toBeFalsy(); }); it("should list the configuration without showing secure values", () => { - runCliScript(__dirname + "/../set/__scripts__/set_secure.sh", TEST_ENVIRONMENT.workingDir, ["profiles.base.properties.secret", "area51"]); + runCliScript(__dirname + "/../set/__scripts__/set_secure.sh", TEST_ENVIRONMENT.workingDir, + ["profiles.project_base.properties.secret", "area51"] + ); const response = runCliScript(__dirname + "/__scripts__/list_config.sh", TEST_ENVIRONMENT.workingDir, [""]); expect(response.stdout.toString()).toMatchSnapshot(); expect(response.stdout.toString()).toContain("secured: secured"); diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/report-env/cli.imperative-test-cli.config.report-env.integration.test.ts b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/report-env/cli.imperative-test-cli.config.report-env.integration.test.ts index 6088da71eb..05622f601d 100644 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/report-env/cli.imperative-test-cli.config.report-env.integration.test.ts +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/report-env/cli.imperative-test-cli.config.report-env.integration.test.ts @@ -86,7 +86,6 @@ describe("imperative-test-cli config report-env", () => { expect(response.error).toBeFalsy(); expect(response.output.toString()).toContain("Zowe CLI version ="); expect(response.output.toString()).toContain("Node.js version ="); - expect(response.output.toString()).toContain("Node Version Manager version ="); expect(response.output.toString()).toContain("O.S. platform ="); expect(response.output.toString()).toContain("O.S. architecture ="); expect(response.output.toString()).toContain("O.S. PATH ="); @@ -101,8 +100,7 @@ describe("imperative-test-cli config report-env", () => { expect(response.output.toString()).toContain("HOME ="); expect(response.output.toString()).toContain("Zowe CLI configuration information"); expect(response.output.toString()).toContain("Zowe daemon mode ="); - expect(response.output.toString()).toContain("Zowe config type = V2 Team Config"); - expect(response.output.toString()).toContain("Team config files in effect:"); + expect(response.output.toString()).toContain("Zowe client config files in use:"); expect(response.output.toString()).toContain("imperative-test-cli.config.json"); expect(response.output.toString()).toContain("Default profile names:"); expect(response.output.toString()).toContain("base = myBase"); @@ -143,7 +141,6 @@ describe("imperative-test-cli config report-env", () => { expect(response.error).toBeFalsy(); expect(response.stdout.toString()).toContain("Zowe CLI version ="); expect(response.stdout.toString()).toContain("Node.js version ="); - expect(response.stdout.toString()).toContain("Node Version Manager version ="); expect(response.stdout.toString()).toContain("O.S. platform ="); expect(response.stdout.toString()).toContain("O.S. architecture ="); expect(response.stdout.toString()).toContain("O.S. PATH ="); @@ -159,8 +156,7 @@ describe("imperative-test-cli config report-env", () => { expect(response.stdout.toString()).toContain("HOME ="); expect(response.stdout.toString()).toContain("Zowe CLI configuration information"); expect(response.stdout.toString()).toContain("Zowe daemon mode ="); - expect(response.stdout.toString()).toContain("Zowe config type = V2 Team Config"); - expect(response.stdout.toString()).toContain("Team config files in effect:"); + expect(response.stdout.toString()).toContain("Zowe client config files in use:"); expect(response.stdout.toString()).toContain("imperative-test-cli.config.json"); expect(response.stdout.toString()).toContain("Default profile names:"); expect(response.stdout.toString()).toContain("base = myBase"); @@ -203,7 +199,6 @@ describe("imperative-test-cli config report-env", () => { expect(response.error).toBeFalsy(); expect(response.stdout.toString()).toContain("Zowe CLI version ="); expect(response.stdout.toString()).toContain("Node.js version ="); - expect(response.stdout.toString()).toContain("Node Version Manager version ="); expect(response.stdout.toString()).toContain("O.S. platform ="); expect(response.stdout.toString()).toContain("O.S. architecture ="); expect(response.stdout.toString()).toContain("O.S. PATH ="); @@ -219,8 +214,7 @@ describe("imperative-test-cli config report-env", () => { expect(response.stdout.toString()).toContain("HOME ="); expect(response.stdout.toString()).toContain("Zowe CLI configuration information"); expect(response.stdout.toString()).toContain("Zowe daemon mode ="); - expect(response.stdout.toString()).toContain("Zowe config type = V2 Team Config"); - expect(response.stdout.toString()).toContain("Team config files in effect:"); + expect(response.stdout.toString()).toContain("Zowe client config files in use:"); expect(response.stdout.toString()).toContain("imperative-test-cli.config.json"); expect(response.stdout.toString()).toContain("Default profile names:"); expect(response.stdout.toString()).toContain("base = myBase"); @@ -264,7 +258,6 @@ describe("imperative-test-cli config report-env", () => { expect(response.error).toBeFalsy(); expect(response.stdout.toString()).toContain("Zowe CLI version ="); expect(response.stdout.toString()).toContain("Node.js version ="); - expect(response.stdout.toString()).toContain("Node Version Manager version ="); expect(response.stdout.toString()).toContain("O.S. platform ="); expect(response.stdout.toString()).toContain("O.S. architecture ="); expect(response.stdout.toString()).toContain("O.S. PATH ="); @@ -280,8 +273,7 @@ describe("imperative-test-cli config report-env", () => { expect(response.stdout.toString()).toContain("HOME ="); expect(response.stdout.toString()).toContain("Zowe CLI configuration information"); expect(response.stdout.toString()).toContain("Zowe daemon mode ="); - expect(response.stdout.toString()).toContain("Zowe config type = V2 Team Config"); - expect(response.stdout.toString()).toContain("Team config files in effect:"); + expect(response.stdout.toString()).toContain("Zowe client config files in use:"); expect(response.stdout.toString()).toContain("imperative-test-cli.config.json"); expect(response.stdout.toString()).toContain("Default profile names:"); expect(response.stdout.toString()).toContain("base = myBase"); @@ -324,7 +316,6 @@ describe("imperative-test-cli config report-env", () => { expect(response.error).toBeFalsy(); expect(response.stdout.toString()).toContain("Zowe CLI version ="); expect(response.stdout.toString()).toContain("Node.js version ="); - expect(response.stdout.toString()).toContain("Node Version Manager version ="); expect(response.stdout.toString()).toContain("O.S. platform ="); expect(response.stdout.toString()).toContain("O.S. architecture ="); expect(response.stdout.toString()).toContain("O.S. PATH ="); @@ -341,8 +332,7 @@ describe("imperative-test-cli config report-env", () => { expect(response.stdout.toString()).toContain("HOME ="); expect(response.stdout.toString()).toContain("Zowe CLI configuration information"); expect(response.stdout.toString()).toContain("Zowe daemon mode ="); - expect(response.stdout.toString()).toContain("Zowe config type = V2 Team Config"); - expect(response.stdout.toString()).toContain("Team config files in effect:"); + expect(response.stdout.toString()).toContain("Zowe client config files in use:"); expect(response.stdout.toString()).toContain("imperative-test-cli.config.json"); expect(response.stdout.toString()).toContain("Default profile names:"); expect(response.stdout.toString()).toContain("base = myBase"); diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/schema/cli.imperative-test-cli.config.schema.integration.test.ts b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/schema/cli.imperative-test-cli.config.schema.integration.test.ts index 7389551188..ccaad18d91 100644 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/schema/cli.imperative-test-cli.config.schema.integration.test.ts +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/schema/cli.imperative-test-cli.config.schema.integration.test.ts @@ -38,8 +38,8 @@ describe("imperative-test-cli config schema", () => { }); it("should print the generated schema", () => { const response = runCliScript(__dirname + "/__scripts__/schema.sh", TEST_ENVIRONMENT.workingDir, [""]); - expect(JSON.parse(response.stdout.toString())).toEqual(expectedSchemaObject); expect(response.stderr.toString()).toEqual(""); expect(response.error).toBeFalsy(); + expect(JSON.parse(response.stdout.toString())).toEqual(expectedSchemaObject); }); }); diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/secure/cli.imperative-test-cli.config.secure.integration.subtest.ts b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/secure/cli.imperative-test-cli.config.secure.integration.subtest.ts index 120ca60d8c..9137c012fa 100644 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/secure/cli.imperative-test-cli.config.secure.integration.subtest.ts +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/secure/cli.imperative-test-cli.config.secure.integration.subtest.ts @@ -12,9 +12,12 @@ import { ITestEnvironment } from "../../../../../../../__src__/environment/doc/response/ITestEnvironment"; import { SetupTestEnvironment } from "../../../../../../../__src__/environment/SetupTestEnvironment"; import { runCliScript } from "../../../../../../../src/TestUtil"; -import { expectedConfigObject, expectedUserConfigObject } from "../__resources__/expectedObjects"; +import { + expectedGlobalConfigObject, expectedGlobalUserConfigObject, + expectedProjectConfigObject, expectedProjectUserConfigObject +} from "../__resources__/expectedObjects"; import * as fs from "fs"; -import { keyring as keytar } from "@zowe/secrets-for-zowe-sdk"; +import { keyring } from "@zowe/secrets-for-zowe-sdk"; import * as path from "path"; import * as lodash from "lodash"; import { IConfigProfile } from "../../../../../../../../src"; @@ -24,18 +27,28 @@ let TEST_ENVIRONMENT: ITestEnvironment; describe("imperative-test-cli config secure", () => { const service = "imperative-test-cli"; - let expectedProjectConfigLocation: string; - let expectedUserConfigLocation: string; - let expectedGlobalProjectConfigLocation: string; + let expectedGlobalConfigLocation: string; let expectedGlobalUserConfigLocation: string; + let expectedProjectConfigLocation: string; + let expectedProjectUserConfigLocation: string; + + const expectedGlobalConfig = lodash.cloneDeep(expectedGlobalConfigObject); + delete expectedGlobalConfig.$schema; + expectedGlobalConfig.profiles.global_base.properties.secret = "(secure value)"; + expectedGlobalConfig.profiles.global_base.secure = ["secret"]; + + const expectedGlobalUserConfig = lodash.cloneDeep(expectedGlobalUserConfigObject); + delete expectedGlobalUserConfig.$schema; + expectedGlobalUserConfig.profiles.global_base.secure = []; // config-init creates user base profiles with an empty secure array - const expectedJson = lodash.cloneDeep(expectedConfigObject); - delete expectedJson.$schema; - expectedJson.profiles.base.properties.secret = "(secure value)"; - expectedJson.profiles.base.secure = ["secret"]; + const expectedProjectConfig = lodash.cloneDeep(expectedProjectConfigObject); + delete expectedProjectConfig.$schema; + expectedProjectConfig.profiles.project_base.properties.secret = "(secure value)"; + expectedProjectConfig.profiles.project_base.secure = ["secret"]; - const expectedUserJson = lodash.cloneDeep(expectedUserConfigObject); - delete expectedUserJson.$schema; + const expectedProjectUserConfig = lodash.cloneDeep(expectedProjectUserConfigObject); + delete expectedProjectUserConfig.$schema; + expectedProjectUserConfig.profiles.project_base.secure = []; // config-init creates user base profiles with an empty secure array // Create the test environment beforeAll(async () => { @@ -44,15 +57,15 @@ describe("imperative-test-cli config secure", () => { testName: "imperative_test_cli_test_config_secure_command" }); expectedGlobalUserConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.user.json"); - expectedGlobalProjectConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.json"); - expectedUserConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.config.user.json"); + expectedGlobalConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.json"); + expectedProjectUserConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.config.user.json"); expectedProjectConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.config.json"); }); afterEach(async () => { runCliScript(__dirname + "/../__scripts__/delete_configs.sh", TEST_ENVIRONMENT.workingDir, ["-rf imperative-test-cli.config.user.json imperative-test-cli.config.json test schema.json"]); - await keytar.deletePassword(service, "secure_config_props"); + await keyring.deletePassword(service, "secure_config_props"); }); afterAll(() => { @@ -62,7 +75,7 @@ describe("imperative-test-cli config secure", () => { it("should display the help", () => { const response = runCliScript(__dirname + "/../__scripts__/get_help.sh", TEST_ENVIRONMENT.workingDir, ["secure"]); - expect(response.output.toString()).toContain(`prompt for secure configuration properties`); + expect(response.output.toString()).toContain(`Prompt for secure configuration properties.`); }); it("should secure the project config", async () => { @@ -71,62 +84,62 @@ describe("imperative-test-cli config secure", () => { const fileContents = JSON.parse(fs.readFileSync(expectedProjectConfigLocation).toString()); const config = runCliScript(__dirname + "/../list/__scripts__/list_config.sh", TEST_ENVIRONMENT.workingDir, ["--rfj"]).stdout.toString(); const configJson = JSON.parse(config); - const securedValue = await keytar.getPassword(service, "secure_config_props"); + const securedValue = await keyring.getPassword(service, "secure_config_props"); const securedValueJson = JSON.parse(Buffer.from(securedValue, "base64").toString()); const expectedSecuredValueJson: any = {}; expectedSecuredValueJson[expectedProjectConfigLocation] = { - "profiles.base.properties.secret": "anotherFakeValue" + "profiles.project_base.properties.secret": "anotherFakeValue" }; expect(response.stderr.toString()).toEqual(""); expect(response.status).toEqual(0); - expect(configJson.data).toEqual(expectedJson); + expect(configJson.data).toEqual(expectedProjectConfig); // Should not contain human readable credentials - expect(fileContents.profiles.base.secure).toEqual(["secret"]); - expect(fileContents.profiles.base.properties).not.toEqual({secret: "anotherFakeValue"}); + expect(fileContents.profiles.project_base.secure).toEqual(["secret"]); + expect(fileContents.profiles.project_base.properties).not.toEqual({secret: "anotherFakeValue"}); // Check the securely stored JSON expect(securedValueJson).toEqual(expectedSecuredValueJson); }); - it("should secure the user config", async () => { + it("should secure the project user config", async () => { runCliScript(__dirname + "/../init/__scripts__/init_config_prompt.sh", TEST_ENVIRONMENT.workingDir, ["--user-config"]); const response = runCliScript(__dirname + "/__scripts__/secure_prompt.sh", TEST_ENVIRONMENT.workingDir, ["--user-config"]); - const fileContents = JSON.parse(fs.readFileSync(expectedUserConfigLocation).toString()); + const fileContents = JSON.parse(fs.readFileSync(expectedProjectUserConfigLocation).toString()); const config = runCliScript(__dirname + "/../list/__scripts__/list_config.sh", TEST_ENVIRONMENT.workingDir, ["--rfj"]).stdout.toString(); const configJson = JSON.parse(config); - const securedValue = await keytar.getPassword(service, "secure_config_props"); - const securedValueJson = (securedValue == null ? null : JSON.parse(Buffer.from(securedValue, "base64").toString())); + const securedValue = await keyring.getPassword(service, "secure_config_props"); + const securedValueJson = securedValue == null ? null : JSON.parse(Buffer.from(securedValue, "base64").toString()); const expectedSecuredValueJson: any = null; expect(response.stderr.toString()).toEqual(""); expect(response.status).toEqual(0); - expect(configJson.data).toEqual(expectedUserJson); + expect(configJson.data).toEqual(expectedProjectUserConfig); // Should not contain human readable credentials - expect(fileContents.profiles.base.secure).not.toEqual(["secret"]); - expect(fileContents.profiles.base.properties).not.toEqual({secret: "anotherFakeValue"}); + expect(fileContents.profiles.project_base.secure).not.toEqual(["secret"]); + expect(fileContents.profiles.project_base.properties).not.toEqual({secret: "anotherFakeValue"}); // Check the securely stored JSON expect(securedValueJson).toEqual(expectedSecuredValueJson); }); - it("should secure the global project config", async () => { + it("should secure the global config", async () => { runCliScript(__dirname + "/../init/__scripts__/init_config_prompt.sh", TEST_ENVIRONMENT.workingDir, ["--global-config"]); const response = runCliScript(__dirname + "/__scripts__/secure_prompt.sh", TEST_ENVIRONMENT.workingDir, ["--global-config"]); - const fileContents = JSON.parse(fs.readFileSync(expectedGlobalProjectConfigLocation).toString()); + const fileContents = JSON.parse(fs.readFileSync(expectedGlobalConfigLocation).toString()); const config = runCliScript(__dirname + "/../list/__scripts__/list_config.sh", TEST_ENVIRONMENT.workingDir, ["--rfj"]).stdout.toString(); const configJson = JSON.parse(config); - const securedValue = await keytar.getPassword(service, "secure_config_props"); + const securedValue = await keyring.getPassword(service, "secure_config_props"); const securedValueJson = JSON.parse(Buffer.from(securedValue, "base64").toString()); const expectedSecuredValueJson: any = {}; - expectedSecuredValueJson[expectedGlobalProjectConfigLocation] = { - "profiles.base.properties.secret": "anotherFakeValue" + expectedSecuredValueJson[expectedGlobalConfigLocation] = { + "profiles.global_base.properties.secret": "anotherFakeValue" }; expect(response.stderr.toString()).toEqual(""); expect(response.status).toEqual(0); - expect(configJson.data).toEqual(expectedJson); + expect(configJson.data).toEqual(expectedGlobalConfig); // Should not contain human readable credentials - expect(fileContents.profiles.base.secure).toEqual(["secret"]); - expect(fileContents.profiles.base.properties).not.toEqual({secret: "anotherFakeValue"}); + expect(fileContents.profiles.global_base.secure).toEqual(["secret"]); + expect(fileContents.profiles.global_base.properties).not.toEqual({secret: "anotherFakeValue"}); // Check the securely stored JSON expect(securedValueJson).toEqual(expectedSecuredValueJson); }); @@ -137,16 +150,16 @@ describe("imperative-test-cli config secure", () => { const fileContents = JSON.parse(fs.readFileSync(expectedGlobalUserConfigLocation).toString()); const config = runCliScript(__dirname + "/../list/__scripts__/list_config.sh", TEST_ENVIRONMENT.workingDir, ["--rfj"]).stdout.toString(); const configJson = JSON.parse(config); - const securedValue = await keytar.getPassword(service, "secure_config_props"); - const securedValueJson = (securedValue == null ? null : JSON.parse(Buffer.from(securedValue, "base64").toString())); + const securedValue = await keyring.getPassword(service, "secure_config_props"); + const securedValueJson = securedValue == null ? null : JSON.parse(Buffer.from(securedValue, "base64").toString()); const expectedSecuredValueJson: any = null; expect(response.stderr.toString()).toEqual(""); expect(response.status).toEqual(0); - expect(configJson.data).toEqual(expectedUserJson); + expect(configJson.data).toEqual(expectedGlobalUserConfig); // Should not contain human readable credentials - expect(fileContents.profiles.base.secure).not.toEqual(["secret"]); - expect(fileContents.profiles.base.properties).not.toEqual({secret: "anotherFakeValue"}); + expect(fileContents.profiles.global_base.secure).not.toEqual(["secret"]); + expect(fileContents.profiles.global_base.properties).not.toEqual({secret: "anotherFakeValue"}); // Check the securely stored JSON expect(securedValueJson).toEqual(expectedSecuredValueJson); }); @@ -166,27 +179,27 @@ describe("imperative-test-cli config secure", () => { ] }; runCliScript(__dirname + "/../set/__scripts__/set.sh", TEST_ENVIRONMENT.workingDir, - ["profiles", JSON.stringify({ base: baseProfile }), "--json"]); + ["profiles", JSON.stringify({ project_base: baseProfile }), "--json"]); const response = runCliScript(__dirname + "/__scripts__/secure_prompt.sh", TEST_ENVIRONMENT.workingDir); const fileContents = JSON.parse(fs.readFileSync(expectedProjectConfigLocation).toString()); const config = runCliScript(__dirname + "/../list/__scripts__/list_config.sh", TEST_ENVIRONMENT.workingDir, ["--rfj"]).stdout.toString(); const configJson = JSON.parse(config); - const expectedJsonWithToken = lodash.cloneDeep(expectedJson); - expectedJsonWithToken.profiles = { base: baseProfile }; - expectedJsonWithToken.profiles.base.properties.tokenValue = "(secure value)"; - const securedValue = await keytar.getPassword(service, "secure_config_props"); + const expectedJsonWithToken = lodash.cloneDeep(expectedProjectConfig); + expectedJsonWithToken.profiles = { project_base: baseProfile }; + expectedJsonWithToken.profiles.project_base.properties.tokenValue = "(secure value)"; + const securedValue = await keyring.getPassword(service, "secure_config_props"); const securedValueJson = JSON.parse(Buffer.from(securedValue, "base64").toString()); const expectedSecuredValueJson: any = {}; expectedSecuredValueJson[expectedProjectConfigLocation] = { - "profiles.base.properties.tokenValue": "fakeUser:anotherFakeValue@fakeToken" + "profiles.project_base.properties.tokenValue": "fakeUser:anotherFakeValue@fakeToken" }; expect(response.stderr.toString()).toEqual(""); expect(response.status).toEqual(0); expect(configJson.data).toEqual(expectedJsonWithToken); // Should not contain human readable credentials - expect(fileContents.profiles.base.secure).toEqual(["tokenValue"]); - expect(fileContents.profiles.base.properties.tokenValue).toBeUndefined(); + expect(fileContents.profiles.project_base.secure).toEqual(["tokenValue"]); + expect(fileContents.profiles.project_base.properties.tokenValue).toBeUndefined(); // Check the securely stored JSON expect(securedValueJson).toEqual(expectedSecuredValueJson); }); diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/set/cli.imperative-test-cli.config.set.integration.subtest.ts b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/set/cli.imperative-test-cli.config.set.integration.subtest.ts index 3bdd5a2090..bfefe5051c 100644 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/set/cli.imperative-test-cli.config.set.integration.subtest.ts +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/config/set/cli.imperative-test-cli.config.set.integration.subtest.ts @@ -12,7 +12,10 @@ import { ITestEnvironment } from "../../../../../../../__src__/environment/doc/response/ITestEnvironment"; import { SetupTestEnvironment } from "../../../../../../../__src__/environment/SetupTestEnvironment"; import { runCliScript } from "../../../../../../../src/TestUtil"; -import { expectedConfigObject, expectedUserConfigObject } from "../__resources__/expectedObjects"; +import { + expectedGlobalConfigObject, expectedGlobalUserConfigObject, + expectedProjectConfigObject, expectedProjectUserConfigObject +} from "../__resources__/expectedObjects"; import * as fs from "fs"; import * as path from "path"; import { keyring as keytar } from "@zowe/secrets-for-zowe-sdk"; @@ -25,20 +28,34 @@ describe("imperative-test-cli config set", () => { const service = "imperative-test-cli"; let expectedProjectConfigLocation: string; let expectedUserConfigLocation: string; - let expectedGlobalProjectConfigLocation: string; + let expectedGlobalConfigLocation: string; let expectedGlobalUserConfigLocation: string; - const expectedJson = lodash.cloneDeep(expectedConfigObject); - delete expectedJson.$schema; - expectedJson.profiles.secured.properties.info = "(secure value)"; - expectedJson.profiles.secured.secure = ["info"]; - expectedJson.profiles.base.properties.secret = "(secure value)"; - expectedJson.profiles.base.secure = ["secret"]; + const expectedProjJson = lodash.cloneDeep(expectedProjectConfigObject); + delete expectedProjJson.$schema; + expectedProjJson.profiles.secured.properties.info = "(secure value)"; + expectedProjJson.profiles.secured.secure = ["info"]; + expectedProjJson.profiles.project_base.properties.secret = "(secure value)"; + expectedProjJson.profiles.project_base.secure = ["secret"]; - const expectedUserJson = lodash.cloneDeep(expectedUserConfigObject); - delete expectedUserJson.$schema; - expectedUserJson.profiles.secured.properties.info = "(secure value)"; - expectedUserJson.profiles.secured.secure = ["info"]; + const expectedGlobalJson = lodash.cloneDeep(expectedGlobalConfigObject); + delete expectedGlobalJson.$schema; + expectedGlobalJson.profiles.secured.properties.info = "(secure value)"; + expectedGlobalJson.profiles.secured.secure = ["info"]; + expectedGlobalJson.profiles.global_base.properties.secret = "(secure value)"; + expectedGlobalJson.profiles.global_base.secure = ["secret"]; + + const expectedProjUserJson = lodash.cloneDeep(expectedProjectUserConfigObject); + delete expectedProjUserJson.$schema; + expectedProjUserJson.profiles.secured.properties.info = "(secure value)"; + expectedProjUserJson.profiles.secured.secure = ["info"]; + expectedProjUserJson.profiles.project_base.secure = []; // config-init creates user base profile with an empty secure array + + const expectedGlobalUserJson = lodash.cloneDeep(expectedGlobalUserConfigObject); + delete expectedGlobalUserJson.$schema; + expectedGlobalUserJson.profiles.secured.properties.info = "(secure value)"; + expectedGlobalUserJson.profiles.secured.secure = ["info"]; + expectedGlobalUserJson.profiles.global_base.secure = []; // config-init creates user base profile with an empty secure array // Create the test environment beforeAll(async () => { @@ -47,7 +64,7 @@ describe("imperative-test-cli config set", () => { testName: "imperative_test_cli_test_config_set_command" }); expectedGlobalUserConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.user.json"); - expectedGlobalProjectConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.json"); + expectedGlobalConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "imperative-test-cli.config.json"); expectedUserConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.config.user.json"); expectedProjectConfigLocation = path.join(TEST_ENVIRONMENT.workingDir, "test", "imperative-test-cli.config.json"); await keytar.setPassword("imperative-test-cli", "secure_config_props", Buffer.from("{}").toString("base64")); @@ -59,7 +76,7 @@ describe("imperative-test-cli config set", () => { it("should display the help", () => { const response = runCliScript(__dirname + "/../__scripts__/get_help.sh", TEST_ENVIRONMENT.workingDir, ["set"]); - expect(response.output.toString()).toContain(`create or update a configuration property`); + expect(response.output.toString()).toContain(`Create or update a configuration property.`); }); it("should store a property in plain text", async () => { runCliScript(__dirname + "/../init/__scripts__/init_config.sh", TEST_ENVIRONMENT.workingDir, ["--user-config"]); @@ -105,20 +122,20 @@ describe("imperative-test-cli config set", () => { const securedValueJson = JSON.parse(Buffer.from(securedValue, "base64").toString()); const expectedSecuredValueJson: any = {}; expectedSecuredValueJson[expectedProjectConfigLocation] = { - "profiles.base.properties.secret": "fakeValue", + "profiles.project_base.properties.secret": "fakeValue", "profiles.secured.properties.info": "some_fake_information" }; expect(response.stderr.toString()).toEqual(""); expect(response.status).toEqual(0); - expect(configJson.data).toEqual(expectedJson); + expect(configJson.data).toEqual(expectedProjJson); // Should not contain human readable credentials expect(fileContents.profiles.secured.secure).toEqual(["info"]); expect(fileContents.profiles.secured.properties).not.toEqual({info: "some_fake_information"}); // Check the securely stored JSON expect(securedValueJson).toEqual(expectedSecuredValueJson); }); - it("should make the info property secure in the user config", async () => { + it("should make the info property secure in the project user config", async () => { runCliScript(__dirname + "/../init/__scripts__/init_config_prompt.sh", TEST_ENVIRONMENT.workingDir, ["--user-config"]); const response = runCliScript(__dirname + "/__scripts__/set_secure.sh", TEST_ENVIRONMENT.workingDir, ["profiles.secured.properties.info", "some_fake_information", "--user-config"]); @@ -134,31 +151,31 @@ describe("imperative-test-cli config set", () => { expect(response.stderr.toString()).toEqual(""); expect(response.status).toEqual(0); - expect(configJson.data).toEqual(expectedUserJson); + expect(configJson.data).toEqual(expectedProjUserJson); // Should not contain human readable credentials expect(fileContents.profiles.secured.secure).toEqual(["info"]); expect(fileContents.profiles.secured.properties).not.toEqual({info: "some_fake_information"}); // Check the securely stored JSON expect(securedValueJson).toEqual(expectedSecuredValueJson); }); - it("should make the info property secure in the global project config", async () => { + it("should make the info property secure in the global config", async () => { runCliScript(__dirname + "/../init/__scripts__/init_config_prompt.sh", TEST_ENVIRONMENT.workingDir, ["--global-config"]); const response = runCliScript(__dirname + "/__scripts__/set_secure.sh", TEST_ENVIRONMENT.workingDir, ["profiles.secured.properties.info", "some_fake_information", "--global-config"]); - const fileContents = JSON.parse(fs.readFileSync(expectedGlobalProjectConfigLocation).toString()); + const fileContents = JSON.parse(fs.readFileSync(expectedGlobalConfigLocation).toString()); const config = runCliScript(__dirname + "/../list/__scripts__/list_config.sh", TEST_ENVIRONMENT.workingDir, ["--rfj"]).stdout.toString(); const configJson = JSON.parse(config); const securedValue = await keytar.getPassword(service, "secure_config_props"); const securedValueJson = JSON.parse(Buffer.from(securedValue, "base64").toString()); const expectedSecuredValueJson: any = {}; - expectedSecuredValueJson[expectedGlobalProjectConfigLocation] = { - "profiles.base.properties.secret": "fakeValue", + expectedSecuredValueJson[expectedGlobalConfigLocation] = { + "profiles.global_base.properties.secret": "fakeValue", "profiles.secured.properties.info": "some_fake_information" }; expect(response.stderr.toString()).toEqual(""); expect(response.status).toEqual(0); - expect(configJson.data).toEqual(expectedJson); + expect(configJson.data).toEqual(expectedGlobalJson); // Should not contain human readable credentials expect(fileContents.profiles.secured.secure).toEqual(["info"]); expect(fileContents.profiles.secured.properties).not.toEqual({info: "some_fake_information"}); @@ -181,7 +198,7 @@ describe("imperative-test-cli config set", () => { expect(response.stderr.toString()).toEqual(""); expect(response.status).toEqual(0); - expect(configJson.data).toEqual(expectedUserJson); + expect(configJson.data).toEqual(expectedGlobalUserJson); // Should not contain human readable credentials expect(fileContents.profiles.secured.secure).toEqual(["info"]); expect(fileContents.profiles.secured.properties).not.toEqual({info: "some_fake_information"}); @@ -204,7 +221,7 @@ describe("imperative-test-cli config set", () => { expect(response.stderr.toString()).toEqual(""); expect(response.status).toEqual(0); - expect(configJson.data).toEqual(expectedUserJson); + expect(configJson.data).toEqual(expectedGlobalUserJson); // Should not contain human readable credentials expect(fileContents.profiles.secured.secure).toEqual(["info"]); expect(fileContents.profiles.secured.properties).not.toEqual({info: {data: "fake"}}); @@ -222,20 +239,20 @@ describe("imperative-test-cli config set", () => { it("should store property securely without --secure flag if found in secure array", async () => { runCliScript(__dirname + "/../init/__scripts__/init_config_prompt.sh", TEST_ENVIRONMENT.workingDir, [""]); const response = runCliScript(__dirname + "/__scripts__/set.sh", TEST_ENVIRONMENT.workingDir, - ["profiles.base.properties.secret", "area51", ""]); + ["profiles.project_base.properties.secret", "area51", ""]); const fileContents = JSON.parse(fs.readFileSync(expectedProjectConfigLocation).toString()); const securedValue = await keytar.getPassword(service, "secure_config_props"); const securedValueJson = JSON.parse(Buffer.from(securedValue, "base64").toString()); const expectedSecuredValueJson: any = {}; expectedSecuredValueJson[expectedProjectConfigLocation] = { - "profiles.base.properties.secret": "area51" + "profiles.project_base.properties.secret": "area51" }; expect(response.stderr.toString()).toEqual(""); expect(response.status).toEqual(0); // Should not contain human readable credentials - expect(fileContents.profiles.base.secure).toEqual(["secret"]); - expect(fileContents.profiles.base.properties).toEqual({}); + expect(fileContents.profiles.project_base.secure).toEqual(["secret"]); + expect(fileContents.profiles.project_base.properties).toEqual({}); // Check the securely stored JSON expect(securedValueJson).toEqual(expectedSecuredValueJson); }); diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/profiles/__scripts__/secured-profile/create_and_list.sh b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/profiles/__scripts__/secured-profile/create_and_list.sh deleted file mode 100644 index 529e20af12..0000000000 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/profiles/__scripts__/secured-profile/create_and_list.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -FORCE_COLOR=0 -OUTPUT="$(imperative-test-cli profiles create secured-profile $2 --info "Not a secret" --secret "$1" --ow)" -RC=$? -if [ $RC -ne 0 ] -then - echo "Create profile command returned a non-zero RC: $?" 1>&2 - echo "$OUTPUT" - exit $RC -fi -imperative-test-cli profiles list secured-profiles --show-contents -RC=$? -if [ $RC -ne 0 ] -then - echo "List profiles command returned a non-zero RC: $?" 1>&2 - exit $RC -fi -exit $? \ No newline at end of file diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/profiles/cli.imperative-test-cli.profiles.create.secured-profile.integration.subtest.ts b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/profiles/cli.imperative-test-cli.profiles.create.secured-profile.integration.subtest.ts deleted file mode 100644 index 0e008ff364..0000000000 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/profiles/cli.imperative-test-cli.profiles.create.secured-profile.integration.subtest.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ITestEnvironment } from "../../../../../../__src__/environment/doc/response/ITestEnvironment"; -import { SetupTestEnvironment } from "../../../../../../__src__/environment/SetupTestEnvironment"; -import { runCliScript } from "../../../../../../src/TestUtil"; - -// Test Environment populated in the beforeAll(); -let TEST_ENVIRONMENT: ITestEnvironment; - -describe("imperative-test-cli profiles create secured-profile", () => { - - // Create the unique test environment - beforeAll(async () => { - TEST_ENVIRONMENT = await SetupTestEnvironment.createTestEnv({ - cliHomeEnvVar: "IMPERATIVE_TEST_CLI_CLI_HOME", - testName: "imperative_test_cli_test_create_secured_profile_command" - }); - }); - - it("should allow us to create a secured profile, list the contents and the secured fields should be hidden", () => { - const secret: string = "supersecretwords"; - const profileName: string = "my_secret"; - const response = runCliScript(__dirname + "/__scripts__/secured-profile/create_and_list.sh", TEST_ENVIRONMENT.workingDir, - [secret, profileName]); - expect(response.stderr.toString()).toContain("command 'profiles create secured-profile' is deprecated"); - expect(response.stderr.toString()).toContain("command 'profiles list secured-profiles' is deprecated"); - expect(response.status).toBe(0); - expect(response.stdout.toString()).not.toContain(secret); - expect(response.stdout.toString()).toContain(profileName); - expect(response.stdout.toString()).toContain("managed by"); - }); -}); diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/test/cli.imperative-test-cli.test.logging.integration.test.ts b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/test/cli.imperative-test-cli.test.logging.integration.test.ts index 1a9fd55447..b50db96221 100644 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/test/cli.imperative-test-cli.test.logging.integration.test.ts +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/test/cli.imperative-test-cli.test.logging.integration.test.ts @@ -9,21 +9,20 @@ * */ +import * as fs from "fs"; +import * as path from "path"; import { runCliScript } from "../../../../../../src/TestUtil"; import { SetupTestEnvironment } from "../../../../../../__src__/environment/SetupTestEnvironment"; import { ITestEnvironment } from "../../../../../../__src__/environment/doc/response/ITestEnvironment"; -import * as fs from "fs"; import { TestLogger } from "../../../../../../src/TestLogger"; -import { LoggerConfigBuilder } from "../../../../../../../src"; +import { LoggerConfigBuilder } from "../../../../../../../src/logger/src/LoggerConfigBuilder"; // Test Environment populated in the beforeAll(); let TEST_ENVIRONMENT: ITestEnvironment; // Log directories -const APP_LOGS_DIR = "/imperative-test-cli/logs/"; -const APP_LOG = APP_LOGS_DIR + "imperative-test-cli.log"; -const IMP_LOGS_DIR = "/imperative/logs/"; -const IMP_LOG = IMP_LOGS_DIR + "imperative.log"; +const APP_LOG = path.join("logs", "imperative-test-cli.log"); +const IMP_LOG = path.join("logs", "imperative.log"); describe("imperative-test-cli test logging command", () => { @@ -51,10 +50,10 @@ describe("imperative-test-cli test logging command", () => { expect(response.stdout.toString()).toMatchSnapshot(); // Make sure the log files are present - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + APP_LOG)).toBe(true); - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + IMP_LOG)).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG))).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG))).toBe(true); - const logContents = fs.readFileSync(TEST_ENVIRONMENT.workingDir + IMP_LOG).toString(); + const logContents = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG)).toString(); // Check for each tag expect(logContents).not.toContain("[TRACE]"); @@ -89,10 +88,10 @@ describe("imperative-test-cli test logging command", () => { expect(response.stdout.toString()).toMatchSnapshot(); // Make sure the log files are present - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + APP_LOG)).toBe(true); - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + IMP_LOG)).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG))).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG))).toBe(true); - const logContents = fs.readFileSync(TEST_ENVIRONMENT.workingDir + APP_LOG).toString(); + const logContents = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG)).toString(); // Check for each tag expect(logContents).not.toContain("[TRACE]"); @@ -132,10 +131,10 @@ describe("imperative-test-cli test logging command", () => { expect(response.stdout.toString()).toMatchSnapshot(); // Make sure the log files are present - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + APP_LOG)).toBe(true); - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + IMP_LOG)).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG))).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG))).toBe(true); - const logContents = fs.readFileSync(TEST_ENVIRONMENT.workingDir + IMP_LOG).toString(); + const logContents = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG)).toString(); // Check for each tag expect(logContents).not.toContain("[TRACE]"); @@ -161,10 +160,10 @@ describe("imperative-test-cli test logging command", () => { expect(response.stdout.toString()).toMatchSnapshot(); // Make sure the log files are present - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + APP_LOG)).toBe(true); - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + IMP_LOG)).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG))).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG))).toBe(true); - const logContents = fs.readFileSync(TEST_ENVIRONMENT.workingDir + IMP_LOG).toString(); + const logContents = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG)).toString(); // Check for each tag expect(logContents).not.toContain("[TRACE]"); @@ -199,10 +198,10 @@ describe("imperative-test-cli test logging command", () => { expect(response.stdout.toString()).toMatchSnapshot(); // Make sure the log files are present - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + APP_LOG)).toBe(true); - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + IMP_LOG)).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG))).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG))).toBe(true); - const logContents = fs.readFileSync(TEST_ENVIRONMENT.workingDir + APP_LOG).toString(); + const logContents = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG)).toString(); // Check for each tag expect(logContents).not.toContain("[TRACE]"); @@ -228,10 +227,10 @@ describe("imperative-test-cli test logging command", () => { expect(response.stdout.toString()).toMatchSnapshot(); // Make sure the log files are present - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + APP_LOG)).toBe(true); - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + IMP_LOG)).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG))).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG))).toBe(true); - const logContents = fs.readFileSync(TEST_ENVIRONMENT.workingDir + APP_LOG).toString(); + const logContents = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG)).toString(); // Check for each tag expect(logContents).not.toContain("[TRACE]"); @@ -265,16 +264,19 @@ describe("imperative-test-cli test logging command", () => { // Set the ENV var for the script const response = runCliScript(__dirname + "/__scripts__/test_logging_cmd.sh", - TEST_ENVIRONMENT.workingDir, [], { IMPERATIVE_TEST_CLI_IMPERATIVE_LOG_LEVEL: "OFF" }); + TEST_ENVIRONMENT.workingDir, [], { + IMPERATIVE_TEST_CLI_IMPERATIVE_LOG_LEVEL: "OFF", + IMPERATIVE_TEST_CLI_APP_LOG_LEVEL: "OFF" + }); expect(response.stderr.toString()).toBe(""); expect(response.status).toBe(0); expect(response.stdout.toString()).toMatchSnapshot(); // Make sure the log files are present - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + APP_LOG)).toBe(true); - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + IMP_LOG)).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG))).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG))).toBe(true); - const logStats = fs.statSync(TEST_ENVIRONMENT.workingDir + IMP_LOG); + const logStats = fs.statSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG)); expect(logStats.size).toBe(0); }); @@ -290,10 +292,10 @@ describe("imperative-test-cli test logging command", () => { expect(response.stdout.toString()).toMatchSnapshot(); // Make sure the log files are present - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + APP_LOG)).toBe(true); - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + IMP_LOG)).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG))).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG))).toBe(true); - const logContents = fs.readFileSync(TEST_ENVIRONMENT.workingDir + IMP_LOG).toString(); + const logContents = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG)).toString(); // Check for each tag expect(logContents).toContain("[TRACE]"); @@ -336,10 +338,10 @@ describe("imperative-test-cli test logging command", () => { expect(response.stdout.toString()).toMatchSnapshot(); // Make sure the log files are present - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + APP_LOG)).toBe(true); - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + IMP_LOG)).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG))).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG))).toBe(true); - const logStats = fs.statSync(TEST_ENVIRONMENT.workingDir + APP_LOG); + const logStats = fs.statSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG)); expect(logStats.size).toBe(0); }); @@ -355,10 +357,10 @@ describe("imperative-test-cli test logging command", () => { expect(response.stdout.toString()).toMatchSnapshot(); // Make sure the log files are present - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + APP_LOG)).toBe(true); - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + IMP_LOG)).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG))).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG))).toBe(true); - const logContents = fs.readFileSync(TEST_ENVIRONMENT.workingDir + APP_LOG).toString(); + const logContents = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG)).toString(); // Check for each tag expect(logContents).toContain("[TRACE]"); @@ -402,13 +404,13 @@ describe("imperative-test-cli test logging command", () => { expect(response.stdout.toString()).toMatchSnapshot(); // Make sure the log files are present - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + APP_LOG)).toBe(true); - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + IMP_LOG)).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG))).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG))).toBe(true); - const appLogStats = fs.statSync(TEST_ENVIRONMENT.workingDir + APP_LOG); + const appLogStats = fs.statSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG)); expect(appLogStats.size).toBe(0); - const impLogStats = fs.statSync(TEST_ENVIRONMENT.workingDir + IMP_LOG); + const impLogStats = fs.statSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG)); expect(impLogStats.size).toBe(0); }); @@ -427,10 +429,10 @@ describe("imperative-test-cli test logging command", () => { expect(response.stdout.toString()).toMatchSnapshot(); // Make sure the log files are present - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + APP_LOG)).toBe(true); - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + IMP_LOG)).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG))).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG))).toBe(true); - const appLogContents = fs.readFileSync(TEST_ENVIRONMENT.workingDir + APP_LOG).toString(); + const appLogContents = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG)).toString(); // Check for each tag expect(appLogContents).toContain("[TRACE]"); @@ -448,7 +450,7 @@ describe("imperative-test-cli test logging command", () => { expect(appLogContents).toContain("This is an app logger error message from the test logging handler!"); expect(appLogContents).toContain("This is an app logger fatal message from the test logging handler!"); - const impLogContents = fs.readFileSync(TEST_ENVIRONMENT.workingDir + IMP_LOG).toString(); + const impLogContents = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG)).toString(); // Check for each tag expect(impLogContents).toContain("[TRACE]"); @@ -482,10 +484,10 @@ describe("imperative-test-cli test logging command", () => { expect(response.stdout.toString()).toMatchSnapshot(); // Make sure the log files are present - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + APP_LOG)).toBe(true); - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + IMP_LOG)).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG))).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG))).toBe(true); - const appLogContents = fs.readFileSync(TEST_ENVIRONMENT.workingDir + APP_LOG).toString(); + const appLogContents = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG)).toString(); // Check for each tag expect(appLogContents).not.toContain("[TRACE]"); @@ -503,7 +505,7 @@ describe("imperative-test-cli test logging command", () => { expect(appLogContents).toContain("This is an app logger error message from the test logging handler!"); expect(appLogContents).toContain("This is an app logger fatal message from the test logging handler!"); - const impLogContents = fs.readFileSync(TEST_ENVIRONMENT.workingDir + IMP_LOG).toString(); + const impLogContents = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG)).toString(); // Check for each tag expect(impLogContents).not.toContain("[TRACE]"); @@ -537,10 +539,10 @@ describe("imperative-test-cli test logging command", () => { expect(response.stdout.toString()).toMatchSnapshot(); // Make sure the log files are present - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + APP_LOG)).toBe(true); - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + IMP_LOG)).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG))).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG))).toBe(true); - const appLogContents = fs.readFileSync(TEST_ENVIRONMENT.workingDir + APP_LOG).toString(); + const appLogContents = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG)).toString(); // Check for each tag expect(appLogContents).not.toContain("[TRACE]"); @@ -559,7 +561,7 @@ describe("imperative-test-cli test logging command", () => { expect(appLogContents).toContain("This is an app logger fatal message from the test logging handler!"); // Read the imperative log contents - const impLogContents = fs.readFileSync(TEST_ENVIRONMENT.workingDir + IMP_LOG).toString(); + const impLogContents = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG)).toString(); // Check for each tag expect(impLogContents).not.toContain("[TRACE]"); @@ -593,15 +595,15 @@ describe("imperative-test-cli test logging command", () => { expect(response.stdout.toString()).toMatchSnapshot(); // Make sure the log files are present - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + APP_LOG)).toBe(true); - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + IMP_LOG)).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG))).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG))).toBe(true); // Ensure that the app log is empty - const appLogStats = fs.statSync(TEST_ENVIRONMENT.workingDir + APP_LOG); + const appLogStats = fs.statSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG)); expect(appLogStats.size).toBe(0); // Ensure that the imp log has all levels - const impLogContents = fs.readFileSync(TEST_ENVIRONMENT.workingDir + IMP_LOG).toString(); + const impLogContents = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG)).toString(); // Check for each tag expect(impLogContents).toContain("[TRACE]"); @@ -635,15 +637,15 @@ describe("imperative-test-cli test logging command", () => { expect(response.stdout.toString()).toMatchSnapshot(); // Make sure the log files are present - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + APP_LOG)).toBe(true); - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + IMP_LOG)).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG))).toBe(true); + expect(fs.existsSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG))).toBe(true); // Ensure that the app log is empty - const impLogStats = fs.statSync(TEST_ENVIRONMENT.workingDir + IMP_LOG); + const impLogStats = fs.statSync(path.join(TEST_ENVIRONMENT.workingDir, IMP_LOG)); expect(impLogStats.size).toBe(0); // Ensure that the imp log has all levels - const appLogStats = fs.readFileSync(TEST_ENVIRONMENT.workingDir + APP_LOG).toString(); + const appLogStats = fs.readFileSync(path.join(TEST_ENVIRONMENT.workingDir, APP_LOG)).toString(); // Check for each tag expect(appLogStats).toContain("[TRACE]"); diff --git a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/test/cli.imperative-test-cli.test.masking.integration.test.ts b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/test/cli.imperative-test-cli.test.masking.integration.test.ts index 50590f95ab..47b85b5b78 100644 --- a/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/test/cli.imperative-test-cli.test.masking.integration.test.ts +++ b/packages/imperative/__tests__/__integration__/imperative/__tests__/__integration__/cli/test/cli.imperative-test-cli.test.masking.integration.test.ts @@ -11,6 +11,7 @@ /* eslint-disable jest/expect-expect */ import * as fs from "fs"; +import * as path from "path"; import { runCliScript } from "../../../../../../src/TestUtil"; import { ITestEnvironment } from "../../../../../../__src__/environment/doc/response/ITestEnvironment"; import { SetupTestEnvironment } from "../../../../../../__src__/environment/SetupTestEnvironment"; @@ -20,10 +21,8 @@ import { TestLogger } from "../../../../../../src/TestLogger"; let TEST_ENVIRONMENT: ITestEnvironment; // Log directories -const APP_LOGS_DIR = "/imperative-test-cli/logs/"; -const APP_LOG = APP_LOGS_DIR + "imperative-test-cli.log"; -const IMP_LOGS_DIR = "/imperative/logs/"; -const IMP_LOG = IMP_LOGS_DIR + "imperative.log"; +const APP_LOG = path.join("logs", "imperative-test-cli.log"); +const IMP_LOG = path.join("logs", "imperative.log"); describe("imperative-test-cli test masking command", () => { // Create the unique test environment @@ -63,8 +62,9 @@ describe("imperative-test-cli test masking command", () => { }; const _testLogs = (_log: string) => { - expect(fs.existsSync(TEST_ENVIRONMENT.workingDir + (_log === "app" ? APP_LOG : IMP_LOG))).toBe(true); - const logContents = fs.readFileSync(TEST_ENVIRONMENT.workingDir + (_log === "app" ? APP_LOG : IMP_LOG)).toString(); + const logPath = path.join(TEST_ENVIRONMENT.workingDir, _log === "app" ? APP_LOG : IMP_LOG); + expect(fs.existsSync(logPath)).toBe(true); + const logContents = fs.readFileSync(logPath).toString(); for (const level of ["trace", "debug", "info", "warn", "error", "fatal"]) { expect(logContents).toContain(`[${level.toUpperCase()}]`); expect(logContents).toContain(_logPrefix(_log, level) + level === "trace" ? "secret" : "****"); diff --git a/packages/imperative/__tests__/__integration__/imperative/package.json b/packages/imperative/__tests__/__integration__/imperative/package.json index 8895054427..34b956b281 100644 --- a/packages/imperative/__tests__/__integration__/imperative/package.json +++ b/packages/imperative/__tests__/__integration__/imperative/package.json @@ -1,6 +1,7 @@ { "name": "imperative-test-cli", "version": "0.0.0", + "zoweVersion": "V99", "description": "Imperative Test CLI", "license": "EPL 2.0", "repository": "", diff --git a/packages/imperative/__tests__/__integration__/imperative/src/cli/auth/FruitAuthHandler.ts b/packages/imperative/__tests__/__integration__/imperative/src/cli/auth/FruitAuthHandler.ts index 1e1fa70006..0cb0fc985f 100644 --- a/packages/imperative/__tests__/__integration__/imperative/src/cli/auth/FruitAuthHandler.ts +++ b/packages/imperative/__tests__/__integration__/imperative/src/cli/auth/FruitAuthHandler.ts @@ -38,6 +38,8 @@ export default class FruitAuthHandler extends BaseAuthHandler { port: 3000, user: args.user, password: args.password, + cert: args.certFile, + certKey: args.certKeyFile, tokenType: args.tokenType, tokenValue: args.tokenValue }; @@ -50,7 +52,11 @@ export default class FruitAuthHandler extends BaseAuthHandler { * @returns {Promise} The response from the auth service containing a token */ protected async doLogin(session: AbstractSession) { - return `${session.ISession.user}:${session.ISession.password}@fakeToken`; + if (session.ISession.user) { + return `${session.ISession.user}:${session.ISession.password}@fakeToken`; + } else { + return `fakeCertificate@fakeToken`; + } } /** diff --git a/packages/imperative/__tests__/__integration__/imperative/src/cli/config/FruitAutoInitHandler.ts b/packages/imperative/__tests__/__integration__/imperative/src/cli/config/FruitAutoInitHandler.ts index 37ed95fb0d..c4a42765bb 100644 --- a/packages/imperative/__tests__/__integration__/imperative/src/cli/config/FruitAutoInitHandler.ts +++ b/packages/imperative/__tests__/__integration__/imperative/src/cli/config/FruitAutoInitHandler.ts @@ -50,8 +50,8 @@ export default class FruitAutoInitHandler extends BaseAutoInitHandler { * @returns {Promise} The response from the auth service containing a token */ protected async doAutoInit(session: AbstractSession, params: IHandlerParameters): Promise { - const tokenType = (session.ISession.type === "basic") ? SessConstants.TOKEN_TYPE_JWT : session.ISession.tokenType; - const tokenValue = (session.ISession.type === "basic") ? + const tokenType = session.ISession.type === "basic" ? SessConstants.TOKEN_TYPE_JWT : session.ISession.tokenType; + const tokenValue = session.ISession.type === "basic" ? `${session.ISession.user}:${session.ISession.password}@fakeToken` : session.ISession.tokenValue; return { profiles: { diff --git a/packages/imperative/__tests__/__integration__/imperative/src/imperative.ts b/packages/imperative/__tests__/__integration__/imperative/src/imperative.ts index 1047412178..3c3f68e855 100644 --- a/packages/imperative/__tests__/__integration__/imperative/src/imperative.ts +++ b/packages/imperative/__tests__/__integration__/imperative/src/imperative.ts @@ -59,6 +59,18 @@ const tokenValueOption: ICommandOptionDefinition = { type: "string" }; +const certFileOption: ICommandOptionDefinition = { + name: "cert-file", + description: "Fruit certificate file", + type: "existingLocalFile" +}; + +const certKeyFileOption: ICommandOptionDefinition = { + name: "cert-key-file", + description: "Fruit certificate key file", + type: "existingLocalFile" +}; + // Example to use with tsnode: */*CommandDefinitions!(.d).*s export const config: IImperativeConfig = { commandModuleGlobs: ["**/cli/*/*definition!(.d).*s"], @@ -148,6 +160,14 @@ export const config: IImperativeConfig = { type: "string", optionDefinition: tokenValueOption, secure: true + }, + certFile: { + type: "existingLocalFile", + optionDefinition: certFileOption + }, + certKeyFile: { + type: "existingLocalFile", + optionDefinition: certKeyFileOption } }, }, @@ -162,7 +182,9 @@ export const config: IImperativeConfig = { hostOption, portOption, userOption, - passwordOption + passwordOption, + certFileOption, + certKeyFileOption ] }, logout: { diff --git a/packages/imperative/__tests__/__src__/environment/SetupTestEnvironment.ts b/packages/imperative/__tests__/__src__/environment/SetupTestEnvironment.ts index f0d7a17ac5..2f65efca32 100644 --- a/packages/imperative/__tests__/__src__/environment/SetupTestEnvironment.ts +++ b/packages/imperative/__tests__/__src__/environment/SetupTestEnvironment.ts @@ -15,7 +15,8 @@ import * as nodePath from "path"; import { TEST_RESULT_DATA_DIR } from "../TestConstants"; import { mkdirpSync } from "fs-extra"; import { ITestEnvironment } from "./doc/response/ITestEnvironment"; -const uuidv4 = require("uuid/v4"); +import { v4 as uuidv4 } from "uuid"; + /** * Use the utility methods here to setup the test environment for running APIs * and CLIs. Imperative will always touch the filesystem in some capacity diff --git a/packages/imperative/__tests__/config/jest.preset.json b/packages/imperative/__tests__/config/jest.preset.json index e718090405..fda74ee2b8 100644 --- a/packages/imperative/__tests__/config/jest.preset.json +++ b/packages/imperative/__tests__/config/jest.preset.json @@ -1,14 +1,11 @@ { - "globals": { - "ts-jest": { - "diagnostics": false, - "tsconfig": "./__tests__/tsconfig.json" - } - }, "moduleFileExtensions": ["ts","js"], "testResultsProcessor": "jest-stare", "testEnvironment": "node", "transform": { - ".(ts)": "ts-jest" + ".(ts)": ["ts-jest", { + "diagnostics": false, + "tsconfig": "packages/imperative/tsconfig-tests.json" + }] } } \ No newline at end of file diff --git a/packages/imperative/__tests__/src/TestUtil.ts b/packages/imperative/__tests__/src/TestUtil.ts index 78cb6d909a..1f2693f558 100644 --- a/packages/imperative/__tests__/src/TestUtil.ts +++ b/packages/imperative/__tests__/src/TestUtil.ts @@ -38,7 +38,7 @@ import { sync } from "cross-spawn"; const yargs = require("yargs").argv; const yaml = require("js-yaml"); const diff = require("deep-diff").diff; -const uuidv4 = require("uuid/v4"); +import { v4 as uuidv4 } from "uuid"; /** * Exports for usage in tests @@ -48,8 +48,8 @@ export { resolve, basename, dirname } from "path"; export const rimraf = (dir: string) => { - const rimrafExecutable = __dirname + "/../../../../node_modules/rimraf/bin.js"; - const rimrafProcess = sync("node", [rimrafExecutable, dir]); + const rimrafExecutable = __dirname + "/../../../../node_modules/rimraf/dist/esm/bin.mjs"; + const rimrafProcess = sync("node", [rimrafExecutable, dir, "--glob"]); if (rimrafProcess.status !== 0) { throw new Error("Error deleting directory with rimraf CLI: \n" + rimrafProcess.output.join(" ")); } @@ -170,10 +170,17 @@ export function executeTestCLICommand(cliBinModule: string, testContext: any, ar execDir?: string, pipeContent?: string | Buffer, env: { [key: string]: string } = process.env): SpawnSyncReturns { const testLogger = TestLogger.getTestLogger(); - const nodeCommand = "node"; - // run the command with ts-node/register - const starterArguments = ["--require", "ts-node/register", cliBinModule]; - args = starterArguments.concat(args); + const isLocalFile = fs.existsSync(cliBinModule) && fs.statSync(cliBinModule).isFile(); + const nodeCommand = isLocalFile ? "node" : "npx"; + if (isLocalFile) { + // run the command with ts-node/register if local file specified + const starterArguments = ["--require", "ts-node/register", cliBinModule]; + args = starterArguments.concat(args); + } else { + // run the command with package bin script if directory specified + args.unshift(Object.keys(require(cliBinModule + "/package.json").bin).pop()); + execDir ??= cliBinModule; + } const commandExecutionMessage = "Executing " + nodeCommand + " " + args.join(" "); @@ -257,8 +264,8 @@ export function findExpectedOutputInCommand(cliBinModule: string, try { jsonOutput = JSON.parse(jsonCommand.stdout); } catch (e) { - const message = ("Error parsing JSON output: stdout:'" + jsonCommand.stdout + "' stderr: '" + jsonCommand.stderr + - "'\n status code " + jsonCommand.status) + " " + e.message; + const message = "Error parsing JSON output: stdout:'" + jsonCommand.stdout + "' stderr: '" + jsonCommand.stderr + + "'\n status code " + jsonCommand.status + " " + e.message; throw new Error(message); } dataObjectParser = new DataObjectParser(jsonOutput); @@ -303,7 +310,7 @@ export function findExpectedOutputInCommand(cliBinModule: string, expectedContent = expectedContent || ""; - if (!(Array.isArray(expectedContent))) { + if (!Array.isArray(expectedContent)) { // convert single expected content to an array expectedContent = [expectedContent]; } @@ -357,8 +364,8 @@ export function compareJsonObjects(actual: any, expected: any, parms?: ICompareP if (parms) { diffs.forEach((difference: any) => { const path = difference.path.join("."); - if (parms.ignorePaths == null || (parms.ignorePaths.indexOf(path) < 0)) { - if (!(parms.pathRegex == null)) { + if (parms.ignorePaths == null || parms.ignorePaths.indexOf(path) < 0) { + if (parms.pathRegex != null) { let regexPathMatch: boolean = false; for (const reg of parms.pathRegex) { if (path === reg.path) { @@ -386,7 +393,7 @@ export function compareJsonObjects(actual: any, expected: any, parms?: ICompareP } }); } else { - if (!(diffs == null)) { + if (diffs != null) { returnDiffs = returnDiffs.concat(diffs); } } @@ -440,7 +447,7 @@ export function runCliScript(scriptPath: string, cwd: string, args: any = [], en // Execute the command synchronously return sync("sh", [`${scriptPath}`].concat(args), {cwd, env: childEnv}); } else { - throw new Error("The script directory doesn't exist"); + throw new Error("The script directory doesn't exist: " + scriptPath); } } diff --git a/packages/imperative/__tests__/src/example_clis/with_bin_package/ProfileBinExampleCLI.ts b/packages/imperative/__tests__/src/example_clis/with_bin_package/ProfileBinExampleCLI.ts old mode 100644 new mode 100755 index c142ccd093..cedeaa80b0 --- a/packages/imperative/__tests__/src/example_clis/with_bin_package/ProfileBinExampleCLI.ts +++ b/packages/imperative/__tests__/src/example_clis/with_bin_package/ProfileBinExampleCLI.ts @@ -1,3 +1,4 @@ +#!/usr/bin/env ts-node /* * This program and the accompanying materials are made available under the terms of the * Eclipse Public License v2.0 which accompanies this distribution, and is available at @@ -16,4 +17,3 @@ Imperative.init({configurationModule: __dirname + "/ProfileBinExampleConfigurati }).catch((error) => { process.stderr.write(`An error occurred parsing or initing: ${error.message}`); }); - diff --git a/packages/imperative/__tests__/src/example_clis/with_bin_package/ProfileBinExampleConfiguration.ts b/packages/imperative/__tests__/src/example_clis/with_bin_package/ProfileBinExampleConfiguration.ts index e8a7a20675..86520ee8f7 100644 --- a/packages/imperative/__tests__/src/example_clis/with_bin_package/ProfileBinExampleConfiguration.ts +++ b/packages/imperative/__tests__/src/example_clis/with_bin_package/ProfileBinExampleConfiguration.ts @@ -11,8 +11,32 @@ import { IImperativeConfig } from "../../../../src/imperative"; -const binConfig: IImperativeConfig = { - commandModuleGlobs: ["definitions/*/*Definition.ts"], +const config: IImperativeConfig = { + definitions: [ + { + name: "log", + description: "Log example messages", + type: "group", + children: [ + { + name: "messages", + description: "Log example messages", + type: "command", + handler: __dirname + "/handlers/LogMessagesHandler", + options: [ + { + name: "level", + allowableValues: {values: ["trace", "debug", "info", "warn", "error", "fatal"]}, + type: "string", + description: "The level to log messages at.", + required: true + } + ] + } + ] + } + ], + commandModuleGlobs: ["../with_bin_package/definitions/*/*Definition.ts"], rootCommandDescription: "Sample command line interface", defaultHome: __dirname + "/../../../__results__/.examplewithprofiles", // defaultHome: createUniqueTestDataDir(), @@ -40,4 +64,4 @@ const binConfig: IImperativeConfig = { }] }; -module.exports = binConfig; +module.exports = config; diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/__integration__/ExampleDefinitions.integration.subtest.ts b/packages/imperative/__tests__/src/example_clis/with_bin_package/__integration__/ExampleDefinitions.integration.test.ts similarity index 88% rename from packages/imperative/__tests__/src/example_clis/with_profiles/__integration__/ExampleDefinitions.integration.subtest.ts rename to packages/imperative/__tests__/src/example_clis/with_bin_package/__integration__/ExampleDefinitions.integration.test.ts index de7af85799..98a734a3aa 100644 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/__integration__/ExampleDefinitions.integration.subtest.ts +++ b/packages/imperative/__tests__/src/example_clis/with_bin_package/__integration__/ExampleDefinitions.integration.test.ts @@ -9,14 +9,12 @@ * */ -import { IImperativeConfig } from "../../../../../src/imperative"; import * as T from "../../../TestUtil"; describe("We should provide the ability to define commands through Javascript objects passed through the config " + "or globs that match modules locally, " + "tested through an example CLI", function () { - const cliBin = __dirname + "/../ProfileExampleCLI.ts"; - const config: IImperativeConfig = require(__dirname + "/../ProfileExampleConfiguration"); + const cliBin = __dirname + "/../ProfileBinExampleCLI.ts"; it("All commands defined through module globs should be accurately defined, " + "and a definition module in the same directory that does not ", diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/__integration__/ExampleLogging.integration.subtest.ts b/packages/imperative/__tests__/src/example_clis/with_bin_package/__integration__/ExampleLogging.integration.test.ts similarity index 91% rename from packages/imperative/__tests__/src/example_clis/with_profiles/__integration__/ExampleLogging.integration.subtest.ts rename to packages/imperative/__tests__/src/example_clis/with_bin_package/__integration__/ExampleLogging.integration.test.ts index 426e0bbf8c..8e3508a54a 100644 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/__integration__/ExampleLogging.integration.subtest.ts +++ b/packages/imperative/__tests__/src/example_clis/with_bin_package/__integration__/ExampleLogging.integration.test.ts @@ -9,14 +9,15 @@ * */ +import * as path from "path"; import * as T from "../../../TestUtil"; import { IImperativeConfig } from "../../../../../src/imperative"; describe("We should provide the ability to create, manage, and use profiles, " + "tested through an example CLI", function () { - const cliBin = __dirname + "/../ProfileExampleCLI.ts"; - const config: IImperativeConfig = require(__dirname + "/../ProfileExampleConfiguration"); - const logFile = config.defaultHome + "/" + config.name + "/logs/" + config.name + ".log"; + const cliBin = __dirname + "/../ProfileBinExampleCLI.ts"; + const config: IImperativeConfig = require(__dirname + "/../ProfileBinExampleConfiguration"); + const logFile = path.join(config.defaultHome as string, "logs", config.name + ".log"); afterEach(function () { T.rimraf(logFile); diff --git a/packages/imperative/__tests__/src/example_clis/with_bin_package/handlers/LogMessagesHandler.ts b/packages/imperative/__tests__/src/example_clis/with_bin_package/handlers/LogMessagesHandler.ts index 08fef83eec..8c3647b681 100644 --- a/packages/imperative/__tests__/src/example_clis/with_bin_package/handlers/LogMessagesHandler.ts +++ b/packages/imperative/__tests__/src/example_clis/with_bin_package/handlers/LogMessagesHandler.ts @@ -13,7 +13,7 @@ import { ICommandHandler, IHandlerParameters } from "../../../../../src/cmd"; import { Imperative } from "../../../../../src/imperative"; -class ProduceLogMessagesHandler implements ICommandHandler { +export default class ProduceLogMessagesHandler implements ICommandHandler { public async process(params: IHandlerParameters): Promise { Imperative.api.appLogger.level = params.arguments.level; Imperative.api.appLogger.trace("This is a trace message"); @@ -25,5 +25,3 @@ class ProduceLogMessagesHandler implements ICommandHandler { params.response.console.log("Log messages were written"); } } - -module.exports = ProduceLogMessagesHandler; diff --git a/packages/imperative/__tests__/src/example_clis/with_bin_package/tsconfig.json b/packages/imperative/__tests__/src/example_clis/with_bin_package/tsconfig.json new file mode 100644 index 0000000000..64498cb3a3 --- /dev/null +++ b/packages/imperative/__tests__/src/example_clis/with_bin_package/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../../../../tsconfig.json" +} \ No newline at end of file diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/ProfileExampleCLI.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/ProfileExampleCLI.ts old mode 100644 new mode 100755 index 8ca0edeb9c..7aff87c698 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/ProfileExampleCLI.ts +++ b/packages/imperative/__tests__/src/example_clis/with_profiles/ProfileExampleCLI.ts @@ -11,10 +11,9 @@ import { Imperative } from "../../../../src/imperative"; - -process.on("unhandledRejection", (err) => { - process.stderr.write("Err: " + err + "\n"); +// Reuse "with_bin_package" configuration without bin script +Imperative.init({configurationModule: __dirname + "/../with_bin_package/ProfileBinExampleConfiguration.ts"}).then(() => { + Imperative.parse(); +}).catch((error) => { + process.stderr.write(`An error occurred parsing or initing: ${error.message}`); }); - -Imperative.init({configurationModule: __dirname + "/ProfileExampleConfiguration.ts"}).then(() => Imperative.parse()); -// Imperative.parse(); diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/ProfileExampleCLINoAutoGen.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/ProfileExampleCLINoAutoGen.ts deleted file mode 100644 index ebca63838d..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/ProfileExampleCLINoAutoGen.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IImperativeConfig, Imperative } from "../../../../src/imperative"; -// load the other config -const config: IImperativeConfig = require(__dirname + "/ProfileExampleConfiguration.ts"); -config.autoGenerateProfileCommands = false; // but turn off the auto generated commands - -Imperative.init(config).then(() => { - Imperative.parse(); -}); - diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/ProfileExampleConfiguration.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/ProfileExampleConfiguration.ts deleted file mode 100644 index a755ed08ea..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/ProfileExampleConfiguration.ts +++ /dev/null @@ -1,229 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IImperativeConfig } from "../../../../src/imperative"; - -const config: IImperativeConfig = { - definitions: [ - { - name: "log", - description: "Log example messages", - type: "group", - children: [ - { - name: "messages", - description: "Log example messages", - type: "command", - handler: __dirname + "/handlers/LogMessagesHandler", - options: [ - { - name: "level", - allowableValues: {values: ["trace", "debug", "info", "warn", "error", "fatal"]}, - type: "string", - description: "The level to log messages at.", - required: true - } - ] - } - ] - }, - { - name: "use-profile-a", - description: "Use a profile of type A", - type: "command", - profile: { - required: ["profile-a"] - }, - handler: __dirname + "/handlers/UseProfileAHandler" - }, - { - name: "use-profile-b", - description: "Use a profile of type B", - type: "command", - profile: { - required: ["profile-b"] - }, - handler: __dirname + "/handlers/UseProfileBHandler" - }, - { - name: "optional-profile-c", - description: "Use a profile of type C", - type: "command", - profile: { - optional: ["profile-c"] - }, - handler: __dirname + "/handlers/OptionalProfileCHandler" - }, - { - name: "use-dependent-profile", - description: "Use a profile of type profile-with-dependency", - type: "command", - profile: { - required: ["profile-with-dependency"] - }, - handler: __dirname + "/handlers/UseDependentProfileHandler" - } - ], - commandModuleGlobs: ["definitions/*/*Definition.ts"], - rootCommandDescription: "Sample command line interface", - defaultHome: __dirname + "/../../../__results__/.examplewithprofiles", - // defaultHome: createUniqueTestDataDir(), - productDisplayName: "Test CLI with Profiles", - name: "example_with_profiles", - profiles: [ - { - type: "profile-a", - schema: { - type: "object", - title: "Example profile type A", - description: "Example profile type A", - properties: { - animal: { - optionDefinition: { - description: "The animal", - type: "string", - name: "animal", aliases: ["a"], - required: true - }, - type: "string", - }, - numberWithDefault: { - optionDefinition: { - defaultValue: 8080, - name: "number-with-default", - type: "number", - description: "A number field with default value", - }, - type: "number" - } - }, - required: ["animal", "numberWithDefault"] - }, - createProfileExamples: [ - { - options: "--animal doggy", - description: "Create a profile-a profile with a doggy as the animal" - } - ], - updateProfileExamples: [ - { - options: "--animal froggy", - description: "Update a profile-a profile to use froggy as the animal" - } - ] - }, - { - type: "profile-b", - schema: { - type: "object", - title: "Example profile type B", - description: "Example profile type B", - properties: { - bumblebee: { - optionDefinition: { - description: "The bumblebee", - type: "string", - name: "bumblebee", aliases: ["b"], - required: true - }, - type: "string", - }, - }, - required: ["bumblebee"] - }, - }, - { - type: "profile-c", - schema: { - type: "object", - title: "Example profile type C", - description: "Example profile type C", - properties: { - animal: { - optionDefinition: { - description: "The animal", - type: "string", - name: "animal", aliases: ["a"], - required: true - }, - type: "string", - }, - }, - required: ["animal"] - }, - }, - { - type: "profile-with-dependency", - schema: { - type: "object", - title: "Example profile with dependent profiles", - description: "Example profile type with dependent profiles", - properties: { - ghost: { - optionDefinition: { - description: "The ghost", - type: "string", - name: "ghost", aliases: ["g"], - required: true - }, - type: "string", - }, - }, - required: ["ghost", "dependencies"] - }, - dependencies: [{ - description: "The profile-a profile to use as a dependency.", - type: "profile-a", - required: true - }] - }, - { - type: "many-field-profile", - validationPlanModule: __dirname + "/plans/ManyFieldValidationPlan", - schema: { - type: "object", - title: "Example profile with multiple fields", - description: "Example profile type with multiple fields", - properties: { - tea: { - optionDefinition: { - description: "The tea", - type: "string", - name: "tea", aliases: ["t"], - required: true - }, - type: "string", - }, - soda: { - optionDefinition: { - description: "The soda", - type: "string", - name: "soda", aliases: ["s"], - required: true - }, - type: "string", - }, - water: { - optionDefinition: { - description: "The water", - type: "string", - name: "water", aliases: ["w"], - required: true - }, - type: "string", - }, - }, - required: ["tea", "soda", "water"] - }, - }] -}; - -export = config; diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/WithProfiles.integration.test.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/WithProfiles.integration.test.ts deleted file mode 100644 index 6dd621c050..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/WithProfiles.integration.test.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -// These tests require access to the same values on the keyring, therefore they cannot run in parallel -// The test order is important - some tests depend on other tests not running first - do not change it -/* eslint-disable max-len */ - -describe("Imperative With Profiles Tests", () => { - require("./__integration__/AutoGeneratedProfileCommands.integration.subtest"); - require("./__integration__/ExampleDefinitions.integration.subtest"); - require("./__integration__/ExampleLogging.integration.subtest"); - require("./__integration__/ExampleProfiles.integration.subtest"); - require("../../packages/cmd/__integration__/HelpCommands.integration.subtest"); -}); diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/__integration__/AutoGeneratedProfileCommands.integration.subtest.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/__integration__/AutoGeneratedProfileCommands.integration.subtest.ts deleted file mode 100644 index 4487177c91..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/__integration__/AutoGeneratedProfileCommands.integration.subtest.ts +++ /dev/null @@ -1,333 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IImperativeConfig } from "../../../../../src/imperative"; -import * as T from "../../../TestUtil"; - -describe("We should provide auto-generated profile commands for convenience, " + - "so that Imperative-based CLIs can let users manage configuration profiles", () => { - const cliBin = __dirname + "/../ProfileExampleCLI.ts"; - const config: IImperativeConfig = require(__dirname + "/../ProfileExampleConfiguration"); - - const profileTypeA = "profile-a"; - const profileTypeB = "profile-b"; - - const manyFieldProfile = "many-field-profile"; - const env = JSON.parse(JSON.stringify(process.env)); - const home = config.defaultHome; - - beforeAll(() => { - T.rimraf(home); - }); - beforeEach(() => { - T.rimraf(home); // delete profiles - }); - afterAll(() => { - T.rimraf(home); - }); - it("If we accept the default of auto-generating profile commands, " + - "commands should be generated for each profile type, " + - "and able to be invoked with --help", () => { - - T.findExpectedOutputInCommand(cliBin, ["profiles", "--help"], ["create", "set"], - "stdout", true, this); - // validate commands have been generated for each type of profile - T.findExpectedOutputInCommand(cliBin, ["profiles", "create", "--help"], [profileTypeA, profileTypeB], - "stdout", true, this); - T.findExpectedOutputInCommand(cliBin, ["profiles", "create", profileTypeA, "--help"], [profileTypeA], - "stdout", true, this); - T.findExpectedOutputInCommand(cliBin, ["profiles", "set", "--help"], [profileTypeA, profileTypeB], - "stdout", true, this); - T.findExpectedOutputInCommand(cliBin, ["profiles", "list", "--help"], [profileTypeA, profileTypeB], - "stdout", true, this); - T.findExpectedOutputInCommand(cliBin, ["profiles", "delete", "--help"], [profileTypeA, profileTypeB], - "stdout", true, this); - T.findExpectedOutputInCommand(cliBin, ["profiles", "update", "--help"], [profileTypeA, profileTypeB], - "stdout", true, this); - T.findExpectedOutputInCommand(cliBin, ["profiles", "validate", "--help"], [manyFieldProfile], - "stdout", true, this); - }); - - it("If we specify updateProfileExamples on our profile configuration, " + - "our examples should appear in the help text", () => { - T.findExpectedOutputInCommand(cliBin, ["profiles", "update", "profile-a", "--help"], ["froggy"], - "stdout", true, this); - - }); - - it("If we turn off auto-generating profile commands, " + - "commands should NOT be generated for each profile type", () => { - const cliBinNoCommands = __dirname + "/../ProfileExampleCLINoAutoGen.ts"; - T.findExpectedOutputInCommand(cliBinNoCommands, ["profiles", "--help"], - ["Command failed due to improper syntax", "Unknown group: profiles"], - "stderr", false, this); - // validate commands have been generated for each type of profile - T.findExpectedOutputInCommand(cliBinNoCommands, ["profiles", "create"], - ["Command failed due to improper syntax", "Unknown group: profiles"], - "stderr", false, this); - T.findExpectedOutputInCommand(cliBinNoCommands, ["profiles", "create", profileTypeA], - ["Command failed due to improper syntax", "Unknown group: profiles"], - "stderr", false, this); - T.findExpectedOutputInCommand(cliBinNoCommands, ["profiles", "set"], - ["Command failed due to improper syntax", "Unknown group: profiles"], - "stderr", false, this); - T.findExpectedOutputInCommand(cliBinNoCommands, ["profiles", "list"], - ["Command failed due to improper syntax", "Unknown group: profiles"], - "stderr", false, this); - T.findExpectedOutputInCommand(cliBinNoCommands, ["profiles", "delete"], - ["Command failed due to improper syntax", "Unknown group: profiles"], - "stderr", false, this); - T.findExpectedOutputInCommand(cliBinNoCommands, ["profiles", "update"], - ["Command failed due to improper syntax", "Unknown group: profiles"], - "stderr", false, this); - }); - - it("If we have a profile type defined with a dependent profile, if we specify a non-existent " + - "profile-a profile, the command should fail", () => { - T.findExpectedOutputInCommand(cliBin, - ["profiles", "create", "profile-with-dependency", - "bad", - "--profile-a-profile", "fake", - "--ghost", "lenore"], - ["fake", "depend"], - "stderr", false, this, T.CMD_TYPE.ALL, {ignoreCase: true}); - }); - - it("If we have a profile type defined with a dependent profile, if we specify a valid " + - "dependent profile, the command should succeed and we should be able to " + - "use the profile on a command", () => { - // basically the simple positive test case for dependent profile creation - const goodDependency = "good"; - const mainProfileName = "big_profile"; - T.findExpectedOutputInCommand(cliBin, ["profiles", "create", profileTypeA, goodDependency, "--animal", "doggy", - ], - ["doggy", "success", "numberWithDefault", "8080"], // expect default number value to be filled in - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - T.findExpectedOutputInCommand(cliBin, - ["profiles", "create", "profile-with-dependency", - mainProfileName, - "--profile-a-profile", goodDependency, - "--ghost", "lenore"], - ["success"], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - // issue a command that uses the new profile with dependency - T.findExpectedOutputInCommand(cliBin, - ["use-dependent-profile"], [], "stdout", - true, this); - }); - - it("If we create a profile-with-dependencies, and the profile-a dependency is different than the default " + - "profile-a profile, the default profile-a profile should not be" + - " loaded when the profile-with-dependencies is used on a command", () => { - const defaultProfileA = "the_default_a_profile"; - const goodDependency = "good"; - const mainProfileName = "big_profile"; - T.findExpectedOutputInCommand(cliBin, ["profiles", "create", profileTypeA, defaultProfileA, "--animal", "emu"], - ["emu", "success"], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - T.findExpectedOutputInCommand(cliBin, ["profiles", "create", profileTypeA, goodDependency, "--animal", "doggy", - ], - ["doggy", "success"], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - T.findExpectedOutputInCommand(cliBin, - ["profiles", "create", "profile-with-dependency", - mainProfileName, - "--profile-a-profile", goodDependency, - "--ghost", "lenore"], - ["success"], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - // issue a command that uses the new profile with dependency - const useProfileOutput = T.findExpectedOutputInCommand(cliBin, - ["use-dependent-profile"], [], "stdout", - true, this); - // default profile shouldn't show up in output - expect(useProfileOutput.stdout.toString().indexOf(defaultProfileA)).toEqual(-1); - }); - - it("If we omit a required option definition on a generate create profile command," + - "defined in the profile schema, " + - "we should get a syntax error", () => { - T.findExpectedOutputInCommand(cliBin, ["profiles", "create", profileTypeA, "bad"], - ["animal"], - "stderr", false, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - }); - - it("We should be able to run through all auto-generated profile commands for two types of profiles", () => { - const firstProfile = "first"; - const secondProfile = "second"; - - // create two A profiles - T.findExpectedOutputInCommand(cliBin, ["profiles", "create", profileTypeA, firstProfile, "--animal", "doggy"], - ["doggy", "success"], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - T.findExpectedOutputInCommand(cliBin, ["profiles", "create", - profileTypeA, secondProfile, "--animal", "sloth"], - ["sloth", "success"], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - // Create two B profiles - T.findExpectedOutputInCommand(cliBin, ["profiles", "create", profileTypeB, firstProfile, "--bumblebee", "dumbledore"], - ["dumbledore", "success"], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - T.findExpectedOutputInCommand(cliBin, ["profiles", "create", profileTypeB, secondProfile, "--bumblebee", "jerry"], - ["jerry", "success"], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - // update second B profile - T.findExpectedOutputInCommand(cliBin, ["profiles", "update", profileTypeB, secondProfile, "--bumblebee", "seinfeld"], - ["seinfeld", "success"], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - // list A type profiles - T.findExpectedOutputInCommand(cliBin, ["profiles", "list", profileTypeA], - [firstProfile, secondProfile], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - // list B type profiles - T.findExpectedOutputInCommand(cliBin, ["profiles", "list", profileTypeB], - [firstProfile, secondProfile], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - // use both A profiles - T.findExpectedOutputInCommand(cliBin, ["use-profile-a"], - [], // default A profile - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - T.findExpectedOutputInCommand(cliBin, ["use-profile-a", "--profile-a-profile", secondProfile], - [], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - // use both B profiles - T.findExpectedOutputInCommand(cliBin, ["use-profile-b"], // default B profile - [], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - T.findExpectedOutputInCommand(cliBin, ["use-profile-b", "--profile-b-profile", secondProfile], - [], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - // set the default A profile to the second and make sure it is used - T.findExpectedOutputInCommand(cliBin, ["profiles", "set", profileTypeA, secondProfile], // default B profile - [], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - T.findExpectedOutputInCommand(cliBin, ["use-profile-a"], // second profile should be used - [], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - // set the default B profile to the second and make sure it is used - T.findExpectedOutputInCommand(cliBin, ["profiles", "set", profileTypeB, secondProfile], // default B profile - [], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - T.findExpectedOutputInCommand(cliBin, ["use-profile-b"], // second profile should be used - [], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - // delete the profiles - T.findExpectedOutputInCommand(cliBin, ["profiles", "delete", profileTypeA, firstProfile, "--force"], - ["success", "delete", firstProfile], "stdout", - true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - T.findExpectedOutputInCommand(cliBin, ["profiles", "delete", profileTypeB, secondProfile, "--force"], - ["success", "delete", secondProfile], "stdout", - true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - }); - - it("should not fail a command where the profile is listed as optional and not specified", () => { - // Optional profiles shouldn't cause a handler or other failure - const output = T.findExpectedOutputInCommand(cliBin, ["optional-profile-c"], // second profile should be used - ["Profile Cs loaded: undefined"], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - expect(output.stderr).toEqual(""); - }); - - it("If we update an existing profile, the contents of the old profile should be merged with teh", () => { - const profileName = "merge_me"; - const oldTea = "earl_grey"; - const oldSoda = "diet_coke"; - const oldWater = "dirty"; - - T.findExpectedOutputInCommand(cliBin, ["profiles", "create", manyFieldProfile, profileName, - "--tea", oldTea, "--soda", oldSoda, "--water", oldWater], - [oldSoda, oldWater, oldTea], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - const newWater = "clean"; - T.findExpectedOutputInCommand(cliBin, ["profiles", "update", manyFieldProfile, profileName, - "--water", newWater], - [oldSoda, newWater, oldTea], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - T.findExpectedOutputInCommand(cliBin, ["profiles", "list", manyFieldProfile, "--show-contents"], - [oldSoda, newWater, oldTea], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - }); - - it("should contain examples specified on profile config in the help text", () => { - T.findExpectedOutputInCommand(cliBin, ["profiles", "create", profileTypeA, "--help"], - ["Examples", "--animal doggy"], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - }); - - it("should be able to validate a many-field-profile with an auto generated validate command", () => { - const profileName = "validate_me"; - const tea = "earl_grey"; - const soda = "diet_coke"; - const water = "dirty"; - - T.findExpectedOutputInCommand(cliBin, ["profiles", "create", manyFieldProfile, profileName, - "--tea", tea, "--soda", soda, "--water", water], - [soda, water, tea], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - T.findExpectedOutputInCommand(cliBin, ["profiles", "validate", manyFieldProfile, profileName], - ["perfect", profileName, "many-field-profile"], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - }); - - it("should not print output more than once if a progress bar is used in a profiles validate command", () => { - const profileName = "validate_me"; - const tea = "earl_grey"; - const soda = "diet_coke"; - const water = "dirty"; - - T.findExpectedOutputInCommand(cliBin, ["profiles", "create", manyFieldProfile, profileName, - "--tea", tea, "--soda", soda, "--water", water], - [soda, water, tea], - "stdout", true, this, T.CMD_TYPE.INTERACTIVE, {ignoreCase: true}); - - const output = T.executeTestCLICommand(cliBin, this, ["profiles", "validate", manyFieldProfile, profileName]); - expect(output.status).toEqual(0); - const stdout = output.stdout.toString(); - // profile summary should only appear once - expect(stdout.match(/PROFILE SUMMARY/gi).length).toEqual(1); - // - }); - - it("should be fail to validate an invalid many-fields-profile", () => { - const profileName = "validate_me"; - const tea = "not_earl_grey"; - const soda = "diet_coke"; - const water = "dirty"; - - T.findExpectedOutputInCommand(cliBin, ["profiles", "create", manyFieldProfile, profileName, - "--tea", tea, "--soda", soda, "--water", water], - [soda, water, tea], - "stdout", true, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - T.findExpectedOutputInCommand(cliBin, ["profiles", "validate", manyFieldProfile, profileName], - ["failed"], - "stdout", false, this, T.CMD_TYPE.JSON, {ignoreCase: true}); - - }); -}); diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/__integration__/ExampleProfiles.integration.subtest.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/__integration__/ExampleProfiles.integration.subtest.ts deleted file mode 100644 index dd78a53156..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/__integration__/ExampleProfiles.integration.subtest.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import * as T from "../../../TestUtil"; -import { IImperativeConfig } from "../../../../../src/imperative"; - -describe("We should provide the ability to create, manage, and use profiles, " + - "tested through an example CLI", function () { - - const config: IImperativeConfig = require(__dirname + "/../ProfileExampleConfiguration"); - it("We should be able to get --help for our example CLI", function () { - T.findExpectedOutputInCommand(__dirname + "/../ProfileExampleCLI", ["--help"], - [config.productDisplayName, "log"], "stdout", true, - this, T.CMD_TYPE.INTERACTIVE); - }); -}); diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/definitions/a/ADefinition.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/definitions/a/ADefinition.ts deleted file mode 100644 index 7aa077568e..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/definitions/a/ADefinition.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandDefinition } from "../../../../../../src/cmd"; - -const definition: ICommandDefinition = { - name: "ape", - type: "group", - description: "Ape commands", - children: [ - { - name: "grape", - type: "command", - description: "An ape eats grapes", - options: [ - { - name: "grape-color", - type: "string", - description: "the color of the grapes eaten by the ape" - } - ] - } - ] -}; - -module.exports = definition; diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/definitions/b/BDefinition.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/definitions/b/BDefinition.ts deleted file mode 100644 index ba5dd4b3f3..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/definitions/b/BDefinition.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandDefinition } from "../../../../../../src/cmd"; - -const definition: ICommandDefinition = { - name: "bat", - type: "group", - description: "Bat commands", - children: [ - { - name: "rat", - type: "command", - description: "A bat eats rats", - options: [ - { - name: "rat-color", - type: "string", - description: "the color of the rat eaten by the bat" - } - ] - } - ] -}; -module.exports = definition; diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/definitions/c/CDefinition.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/definitions/c/CDefinition.ts deleted file mode 100644 index d0aee7aafc..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/definitions/c/CDefinition.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandDefinition } from "../../../../../../src/cmd"; - -const definition: ICommandDefinition = { - name: "cat", - type: "group", - description: "Cat commands", - children: [ - { - name: "splat", - type: "command", - description: "A cat eats splats", - options: [ - { - name: "splat-color", - type: "string", - description: "the color of the splat eaten by the cat" - } - ] - } - ] -}; -module.exports = definition; diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/definitions/d/DDefinition.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/definitions/d/DDefinition.ts deleted file mode 100644 index 2a7f746fac..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/definitions/d/DDefinition.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandDefinition } from "../../../../../../src/cmd"; - -const definition: ICommandDefinition = { - name: "dog", - type: "group", - description: "Dog commands", - children: [ - { - name: "log", - type: "command", - description: "A dog eats logs", - options: [ - { - name: "log-color", - type: "string", - description: "the color of the log eaten by the dog" - } - ] - } - ] -}; -module.exports = definition; diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/definitions/d/DoNotIncludeMe.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/definitions/d/DoNotIncludeMe.ts deleted file mode 100644 index bea26ce1c2..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/definitions/d/DoNotIncludeMe.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandDefinition } from "../../../../../../src/cmd"; - -const definition: ICommandDefinition = { - name: "do-not-include-this", - type: "group", - description: "These commands should not match the glob and thus should not be defined", - children: [ - { - name: "or-this", - type: "command", - description: "Don't include this either", - options: [ - { - name: "this-color", - type: "string", - description: "the color of the this that you shouldn't include" - } - ] - } - ] -}; -module.exports = definition; diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/handlers/LogMessagesHandler.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/handlers/LogMessagesHandler.ts deleted file mode 100644 index 8c3647b681..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/handlers/LogMessagesHandler.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandHandler, IHandlerParameters } from "../../../../../src/cmd"; -import { Imperative } from "../../../../../src/imperative"; - - -export default class ProduceLogMessagesHandler implements ICommandHandler { - public async process(params: IHandlerParameters): Promise { - Imperative.api.appLogger.level = params.arguments.level; - Imperative.api.appLogger.trace("This is a trace message"); - Imperative.api.appLogger.debug("This is a debug message"); - Imperative.api.appLogger.info("This is an info message"); - Imperative.api.appLogger.warn("This is a warn message"); - Imperative.api.appLogger.error("This is an error message"); - Imperative.api.appLogger.fatal("This is a fatal message"); - params.response.console.log("Log messages were written"); - } -} diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/handlers/OptionalProfileCHandler.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/handlers/OptionalProfileCHandler.ts deleted file mode 100644 index 6122fd06a4..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/handlers/OptionalProfileCHandler.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandHandler, IHandlerParameters } from "../../../../../src/cmd"; - -export default class OptionalProfileCHandler implements ICommandHandler { - public async process(params: IHandlerParameters) { - // eslint-disable-next-line deprecation/deprecation - const profile = params.profiles.get("profile-c", false); - params.response.console.log(`Profile Cs loaded: ${profile}`); - } -} diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/handlers/UseDependentProfileHandler.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/handlers/UseDependentProfileHandler.ts deleted file mode 100644 index 94722840a3..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/handlers/UseDependentProfileHandler.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandHandler, IHandlerParameters } from "../../../../../src/cmd"; - -export default class UseDependentProfile implements ICommandHandler { - public async process(params: IHandlerParameters) { - // eslint-disable-next-line deprecation/deprecation - const dependencyProfile = params.profiles.get("profile-a"); - params.response.console.log("Loaded profile dependency of type profile-a"); - // eslint-disable-next-line deprecation/deprecation - const mainProfile = params.profiles.get("profile-with-dependency"); - params.response.console.log("Loaded main profile of type profile-with-dependency"); - } -} diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/handlers/UseProfileAHandler.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/handlers/UseProfileAHandler.ts deleted file mode 100644 index 1745880c01..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/handlers/UseProfileAHandler.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandHandler, IHandlerParameters } from "../../../../../src/cmd"; - -export default class UseProfileAHandler implements ICommandHandler { - public async process(params: IHandlerParameters) { - // eslint-disable-next-line deprecation/deprecation - const profile = params.profiles.get("profile-a"); - params.response.console.log("Loaded profile {{name}} of type {{type}}", - {name: profile.name, type: profile.type}); - } -} diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/handlers/UseProfileBHandler.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/handlers/UseProfileBHandler.ts deleted file mode 100644 index 246abae3c1..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/handlers/UseProfileBHandler.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandHandler, IHandlerParameters } from "../../../../../src/cmd"; - -export default class UseProfileAHandler implements ICommandHandler { - public async process(params: IHandlerParameters): Promise { - // eslint-disable-next-line deprecation/deprecation - const profile = params.profiles.get("profile-b"); - params.response.console.log("Loaded profile {{name}} of type {{type}}", - {name: profile.name, type: profile.type}); - } -} - diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/package.json b/packages/imperative/__tests__/src/example_clis/with_profiles/package.json deleted file mode 100644 index feedaf6726..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "profile-example-cli", - "version": "0.0.0", - "description": "Test Imperative CLI with Profiles", - "license": "EPL 2.0", - "repository": "", - "author": { - "name": "", - "email": "", - "url": "" - }, - "keywords": [ - "" - ], - "files": [ - "lib" - ], - "main": "lib/index.js", - "typings": "lib/index.d.ts", - "scripts": { - }, - "dependencies": { - }, - "devDependencies": { - }, - "engines": { - "node": ">=6.0.0" - } -} diff --git a/packages/imperative/__tests__/src/example_clis/with_profiles/plans/ManyFieldValidationPlan.ts b/packages/imperative/__tests__/src/example_clis/with_profiles/plans/ManyFieldValidationPlan.ts deleted file mode 100644 index 8e8b8d9d74..0000000000 --- a/packages/imperative/__tests__/src/example_clis/with_profiles/plans/ManyFieldValidationPlan.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IProfileValidationPlan, IProfileValidationTask } from "../../../../../src/profiles"; -import { IProfileValidationTaskResult } from "../../../../../src/profiles/src/validation/doc/IProfileValidationTaskResult"; - -export = class ManyFieldValidationPlan implements IProfileValidationPlan { - - public get tasks(): IProfileValidationTask[] { - return [ - { - description: "Tea should be earl_grey", - name: "Tea color", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - let result: IProfileValidationTaskResult; - if (profile.tea == null || profile.tea !== "earl_grey") { - result = { - outcome: "Failed", - resultDescription: "Tea was not earl_grey" - }; - } else { - result = { - outcome: "OK", - resultDescription: "Tea was earl_grey" - }; - } - done(result); - } - } - ]; - } - - public get failureSuggestions(): string { - return "Get earl grey tea"; - } -}; diff --git a/packages/imperative/__tests__/src/packages/cmd/ValidationTestCommand.ts b/packages/imperative/__tests__/src/packages/cmd/ValidationTestCommand.ts index 633374e0d8..31922285ab 100644 --- a/packages/imperative/__tests__/src/packages/cmd/ValidationTestCommand.ts +++ b/packages/imperative/__tests__/src/packages/cmd/ValidationTestCommand.ts @@ -68,6 +68,7 @@ export const ValidationTestCommand: ICommandDefinition = { name: "should-be-number", description: "should be a numerical value", type: "number", + aliases: ["sbn"] }, { name: "dog-type", diff --git a/packages/imperative/__tests__/src/packages/cmd/__integration__/CliProfileManager.integration.test.ts b/packages/imperative/__tests__/src/packages/cmd/__integration__/CliProfileManager.integration.test.ts deleted file mode 100644 index ff0d7920f3..0000000000 --- a/packages/imperative/__tests__/src/packages/cmd/__integration__/CliProfileManager.integration.test.ts +++ /dev/null @@ -1,208 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -jest.mock("../../../../../src/utilities/src/ImperativeConfig"); - -import { inspect } from "util"; -import { rimraf, TEST_RESULT_DIR } from "../../../TestUtil"; -import { TestLogger } from "../../../../src/TestLogger"; -import { CliProfileManager } from "../../../../../src/cmd/src/profiles/CliProfileManager"; -import { ICommandProfileTypeConfiguration } from "../../../../../src/cmd"; - -describe("Cli Profile Manager", () => { - const profileDir = TEST_RESULT_DIR + "/cliprofilemanager"; - const testLogger = TestLogger.getTestLogger(); - const profileTypeOne = "banana"; - - const addTwoNumbersHandler = __dirname + "/../profileHandlers/AddTwoNumbersHandler"; - afterEach(() => { - rimraf(profileDir); - }); - - const getTypeConfigurations: () => ICommandProfileTypeConfiguration[] = () => { - return [{ - type: profileTypeOne, - schema: { - type: "object", - title: "test profile", - description: "test profile", - properties: { - sum: { - type: "number" - } - }, - required: ["sum"] - }, - }]; - }; - it("should take a handler to create a profile from command line arguments, and " + - "the handler should be called and the resulting profile should have the created fields in it.", async () => { - const configs = getTypeConfigurations(); - configs[0].createProfileFromArgumentsHandler = addTwoNumbersHandler; - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - const a = 1; - const b = 2; - const profileName = "myprofile"; - const saveResult = await manager.save({ - name: profileName, type: profileTypeOne, - profile: {}, - args: {_: [], $0: "test", a, b} - }); - testLogger.info("Save profile result: " + inspect(saveResult)); - const loadedProfile: any = await manager.load({name: profileName}); - expect(loadedProfile.profile.sum).toEqual(a + b); - }); - - - it("If we provide a non existent handler to create a profile from command line arguments, " + - "we should get a helpful error.", async () => { - const configs = getTypeConfigurations(); - configs[0].createProfileFromArgumentsHandler = __dirname + "/profileHandlers/fakearooni"; - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - try { - await manager.save({ - name: "badprofile", type: profileTypeOne, - profile: {sum: 2}, - args: {_: [], $0: "test", doesNotMatter: "hi"} - }); - } catch (e) { - testLogger.info("Received error as expected: " + inspect(e)); - expect(e.message).toContain("handler"); - expect(e.message.toLowerCase()).toContain("error"); - } - }); - - it("should take a handler to update a profile that has already been created," + - " call the handler and update the profile from arguments.", - async () => { - const configs = getTypeConfigurations(); - configs[0].updateProfileFromArgumentsHandler = addTwoNumbersHandler; - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - const a = 1; - const b = 2; - const originalSum = 55; - const profileName = "myprofile"; - const saveResult = await manager.save({ - name: profileName, type: profileTypeOne, - profile: {sum: originalSum} - }); - expect(saveResult.overwritten).toEqual(false); - - testLogger.info("Save profile result: " + inspect(saveResult)); - - const updateResult = await manager.update({ - name: profileName, type: profileTypeOne, - profile: { - sum: 1 - }, - args: {_: [], $0: "fake", a, b} - }); - expect(updateResult.profile.sum).toEqual(a + b); - - testLogger.info("Update profile result: " + inspect(updateResult)); - const loadedProfile: any = await manager.load({name: profileName}); - testLogger.info("Loaded profile after update: " + inspect(loadedProfile)); - expect(loadedProfile.profile.sum).toEqual(a + b); - }); - - it("If we provide a non existent handler to update a profile from command line arguments, " + - "we should get a helpful error.", async () => { - const configs = getTypeConfigurations(); - configs[0].updateProfileFromArgumentsHandler = __dirname + "/profileHandlers/fakearooni"; - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - const profileName = "badprofile"; - await manager.save({ - name: profileName, type: profileTypeOne, - profile: {sum: 30} - }); - try { - await manager.update({ - name: profileName, type: profileTypeOne, - profile: {sum: 2}, - args: {_: [], $0: "test", doesNotMatter: "hi"} - }); - } catch (e) { - testLogger.info("Received error as expected: " + inspect(e)); - expect(e.message).toContain("handler"); - expect(e.message.toLowerCase()).toContain("error"); - } - }); - - it("should be able to automatically map command line options to " + - "profile fields without a handler for a simple single layer " + - "profile schema", async () => { - // use different option names than the field names - // of the profile to test that the properties are associated - // with the correct command line options - const configs: ICommandProfileTypeConfiguration[] = [{ - type: profileTypeOne, - schema: { - type: "object", - title: "test profile", - description: "test profile", - properties: { - property1: { - type: "number", - optionDefinition: { - name: "differentProperty1", type: "number", description: "property1" - } - }, - property2: { - type: "string", - optionDefinition: { - name: "differentProperty2", type: "string", description: "property2" - } - } - }, - required: ["property1"] - }, - }]; - - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - const propertyOneValue = 345; - const propertyTwoValue = "cell phone"; - const profileName = "myprofile"; - const saveResult = await manager.save({ - name: profileName, type: profileTypeOne, - profile: {}, - args: {_: [], $0: "test", differentProperty1: propertyOneValue, differentProperty2: propertyTwoValue} - }); - testLogger.info("Save profile result: " + inspect(saveResult)); - const loadedProfile: any = await manager.load({name: profileName}); - expect(loadedProfile.profile.property1).toEqual(propertyOneValue); - expect(loadedProfile.profile.property2).toEqual(propertyTwoValue); - }); -}); diff --git a/packages/imperative/__tests__/src/packages/cmd/__integration__/HelpCommands.integration.subtest.ts b/packages/imperative/__tests__/src/packages/cmd/__integration__/HelpCommands.integration.test.ts similarity index 63% rename from packages/imperative/__tests__/src/packages/cmd/__integration__/HelpCommands.integration.subtest.ts rename to packages/imperative/__tests__/src/packages/cmd/__integration__/HelpCommands.integration.test.ts index 19139af974..4ea5996a96 100644 --- a/packages/imperative/__tests__/src/packages/cmd/__integration__/HelpCommands.integration.subtest.ts +++ b/packages/imperative/__tests__/src/packages/cmd/__integration__/HelpCommands.integration.test.ts @@ -13,8 +13,9 @@ import * as T from "../../../TestUtil"; import { IImperativeConfig } from "../../../../../src/imperative/index"; describe("Imperative help should be available for a range of definitions", function () { - const withBinPackageCliBin = __dirname + "/../../../example_clis/with_bin_package/ProfileBinExampleCLI"; - const profileCliBin = __dirname + "/../../../example_clis/with_profiles/ProfileExampleCLI"; + const cliWithBin = __dirname + "/../../../example_clis/with_bin_package"; + const cliWithoutBin = __dirname + "/../../../example_clis/with_profiles/ProfileExampleCLI.ts"; + const config: IImperativeConfig = require(__dirname + "/../../../example_clis/with_bin_package/ProfileBinExampleConfiguration"); /** * Clean up the home directory before and after each test. */ @@ -22,39 +23,35 @@ describe("Imperative help should be available for a range of definitions", funct T.rimraf(T.TEST_HOME); }); afterEach(function () { - T.rimraf(T.TEST_HOME); }); - const config: IImperativeConfig = require(__dirname + "/../../../example_clis/with_profiles/ProfileExampleConfiguration"); - const binConfig: IImperativeConfig = require(__dirname + "/../../../example_clis/with_bin_package/ProfileBinExampleConfiguration"); - it("We should be able to get --help for our example CLI - no bin specified in package", function () { - T.findExpectedOutputInCommand(profileCliBin, ["--help"], + T.findExpectedOutputInCommand(cliWithoutBin, ["--help"], [config.productDisplayName, "log"], "stdout", true, this, T.CMD_TYPE.INTERACTIVE); - T.findExpectedOutputInCommand(profileCliBin, ["log", "--help"], + T.findExpectedOutputInCommand(cliWithoutBin, ["log", "--help"], ["ProfileExampleCLI.ts", "Log example messages", "messages"], "stdout", true, this, T.CMD_TYPE.INTERACTIVE); - T.findExpectedOutputInCommand(profileCliBin, ["log", "messages", "--help"], + T.findExpectedOutputInCommand(cliWithoutBin, ["log", "messages", "--help"], ["ProfileExampleCLI.ts", "Log example messages", "messages", "level"], "stdout", true, this, T.CMD_TYPE.INTERACTIVE); }); it("should display --version in the root help", function () { - T.findExpectedOutputInCommand(withBinPackageCliBin, ["--help"], - [binConfig.productDisplayName, "--version"], "stdout", true, + T.findExpectedOutputInCommand(cliWithBin, ["--help"], + [config.productDisplayName, "--version"], "stdout", true, this, T.CMD_TYPE.INTERACTIVE); }); it("We should be able to get --help for our example CLI - with bin in package", function () { - T.findExpectedOutputInCommand(withBinPackageCliBin, ["--help"], - [binConfig.productDisplayName, "ape", "bat", "cat"], "stdout", true, + T.findExpectedOutputInCommand(cliWithBin, ["--help"], + [config.productDisplayName, "ape", "bat", "cat"], "stdout", true, this, T.CMD_TYPE.INTERACTIVE); - T.findExpectedOutputInCommand(withBinPackageCliBin, ["ape", "--help"], + T.findExpectedOutputInCommand(cliWithBin, ["ape", "--help"], ["sample-with-bin", "An ape eats grapes"], "stdout", true, this, T.CMD_TYPE.INTERACTIVE); - T.findExpectedOutputInCommand(withBinPackageCliBin, ["ape", "grape", "--help"], + T.findExpectedOutputInCommand(cliWithBin, ["ape", "grape", "--help"], ["sample-with-bin", "--grape-color", "the color of the grapes eaten by the ape"], "stdout", true, this, T.CMD_TYPE.INTERACTIVE); }); diff --git a/packages/imperative/__tests__/src/packages/cmd/__integration__/SyntaxValidator.integration.test.ts b/packages/imperative/__tests__/src/packages/cmd/__integration__/SyntaxValidator.integration.test.ts index a88c6a85df..cde77a8f29 100644 --- a/packages/imperative/__tests__/src/packages/cmd/__integration__/SyntaxValidator.integration.test.ts +++ b/packages/imperative/__tests__/src/packages/cmd/__integration__/SyntaxValidator.integration.test.ts @@ -10,7 +10,8 @@ */ /* eslint-disable jest/expect-expect */ -import { CommandProcessor, ICommandDefinition, ICommandResponse } from "../../../../../src/cmd/index"; +import { CommandProcessor } from "../../../../../src/cmd/src/CommandProcessor"; +import { ICommandDefinition, ICommandResponse } from "../../../../../src/cmd/index"; import { ValidationTestCommand } from "../ValidationTestCommand"; import { Constants } from "../../../../../src/constants/index"; import { Imperative } from "../../../../../src/imperative/src/Imperative"; @@ -18,7 +19,7 @@ import { TestLogger } from "../../../../src/TestLogger"; import { createUniqueTestDataDir, rimraf } from "../../../TestUtil"; import { AbstractHelpGenerator } from "../../../../../src/cmd/src/help/abstract/AbstractHelpGenerator"; import { DefaultHelpGenerator } from "../../../../../src/cmd/src/help/DefaultHelpGenerator"; -import { BasicProfileManagerFactory, IProfileTypeConfiguration } from "../../../../../src/index"; +import { IProfileTypeConfiguration, ImperativeConfig } from "../../../../../src/index"; const ENV_PREFIX = "INTEGRATION_TEST"; const TEST_HOME = createUniqueTestDataDir(); @@ -43,15 +44,9 @@ const DUMMY_PROFILE_TYPE_CONFIG: IProfileTypeConfiguration[] = [ ]; describe("Imperative should provide advanced syntax validation rules", function () { const home = __dirname + "/validationtests"; - // eslint-disable-next-line deprecation/deprecation - const mainModule = process.mainModule; - beforeAll(function () { - // eslint-disable-next-line deprecation/deprecation - (process.mainModule as any) = { - filename: __filename - }; - return Imperative.init({ + beforeAll(async function () { + await Imperative.init({ productDisplayName: "Validation tests", definitions: [{ name: "banana", @@ -60,10 +55,9 @@ describe("Imperative should provide advanced syntax validation rules", function }], defaultHome: home, }); + ImperativeConfig.instance.callerLocation = __filename; }); afterAll(() => { - // eslint-disable-next-line deprecation/deprecation - process.mainModule = mainModule; rimraf(home); }); describe("Advanced syntax validation for commands using a test command", function () { @@ -95,7 +89,6 @@ describe("Imperative should provide advanced syntax validation rules", function definition: ValidationTestCommand, fullDefinition: fakeParent, helpGenerator, - profileManagerFactory: new BasicProfileManagerFactory(TEST_HOME, DUMMY_PROFILE_TYPE_CONFIG), rootCommandName: "fakeroot", commandLine: "fakecommand", promptPhrase: "fakefakefake" @@ -108,7 +101,7 @@ describe("Imperative should provide advanced syntax validation rules", function } else { expect(completedResponse.success).toEqual(false); } - if (!(expectedText == null) && expectedText.length > 0) { + if (expectedText != null && expectedText.length > 0) { (completedResponse.stderr as any) = completedResponse.stderr.toString(); (completedResponse.stdout as any) = completedResponse.stdout.toString(); for (const text of expectedText) { @@ -452,8 +445,6 @@ describe("Imperative should provide advanced syntax validation rules", function definition: numberCommand, fullDefinition: fakeParent, helpGenerator, - profileManagerFactory: new BasicProfileManagerFactory(TEST_HOME, - DUMMY_PROFILE_TYPE_CONFIG), rootCommandName: "fake", commandLine: "fake", promptPhrase: "fakefakefake" @@ -483,8 +474,6 @@ describe("Imperative should provide advanced syntax validation rules", function definition: numberCommand, fullDefinition: fakeParent, helpGenerator, - profileManagerFactory: new BasicProfileManagerFactory(TEST_HOME, - DUMMY_PROFILE_TYPE_CONFIG), rootCommandName: "fake", commandLine: "fake", promptPhrase: "fakefakefake" @@ -537,8 +526,6 @@ describe("Imperative should provide advanced syntax validation rules", function definition: numberCommand, fullDefinition: fakeParent, helpGenerator, - profileManagerFactory: new BasicProfileManagerFactory(TEST_HOME, - DUMMY_PROFILE_TYPE_CONFIG), rootCommandName: "fake", commandLine: "fake", promptPhrase: "dummydummy" @@ -571,8 +558,6 @@ describe("Imperative should provide advanced syntax validation rules", function definition: numberCommand, fullDefinition: fakeParent, helpGenerator, - profileManagerFactory: new BasicProfileManagerFactory(TEST_HOME, - DUMMY_PROFILE_TYPE_CONFIG), rootCommandName: "fake", commandLine: "fake", promptPhrase: "fakefakefake" @@ -602,8 +587,6 @@ describe("Imperative should provide advanced syntax validation rules", function definition: numberCommand, fullDefinition: fakeParent, helpGenerator, - profileManagerFactory: new BasicProfileManagerFactory(TEST_HOME, - DUMMY_PROFILE_TYPE_CONFIG), rootCommandName: "fake", commandLine: "fake", promptPhrase: "dummydummy" diff --git a/packages/imperative/__tests__/src/packages/cmd/profileHandlers/AddTwoNumbersHandler.ts b/packages/imperative/__tests__/src/packages/cmd/profileHandlers/AddTwoNumbersHandler.ts deleted file mode 100644 index 117d409014..0000000000 --- a/packages/imperative/__tests__/src/packages/cmd/profileHandlers/AddTwoNumbersHandler.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandHandler, IHandlerParameters } from "../../../../../src/cmd"; - -export default class AddTwoNumbersHandler implements ICommandHandler { - public async process(params: IHandlerParameters): Promise { - const sum = params.arguments.a + params.arguments.b; - params.response.console.log("updated sum to: " + sum); - params.response.data.setObj({sum}); - } -} diff --git a/packages/imperative/__tests__/src/packages/imperative/__integration__/ConfigLoading.integration.test.ts b/packages/imperative/__tests__/src/packages/imperative/__integration__/ConfigLoading.integration.subtest.ts similarity index 57% rename from packages/imperative/__tests__/src/packages/imperative/__integration__/ConfigLoading.integration.test.ts rename to packages/imperative/__tests__/src/packages/imperative/__integration__/ConfigLoading.integration.subtest.ts index 22044b80cb..e4bdf9ba95 100644 --- a/packages/imperative/__tests__/src/packages/imperative/__integration__/ConfigLoading.integration.test.ts +++ b/packages/imperative/__tests__/src/packages/imperative/__integration__/ConfigLoading.integration.subtest.ts @@ -12,28 +12,26 @@ import * as T from "../../../TestUtil"; import { IImperativeConfig, Imperative } from "../../../../../src/imperative"; import { ImperativeConfig } from "../../../../../src/utilities"; +import { dirname } from "path"; +import { existsSync } from "fs"; describe("Imperative should validate config provided by the consumer", function () { - const testDir = T.createUniqueTestDataDir("config-loading"); - const packageJsonPath = testDir + "/package.json"; - // eslint-disable-next-line deprecation/deprecation - const mainModule = process.mainModule; - - beforeAll(() => { - // Temporarily change the main module filename so that the test can work. - // eslint-disable-next-line deprecation/deprecation - (process.mainModule as any) = { - filename: packageJsonPath - }; - }); + let packageJsonPath: string; + // This is just to satisfy the type check. As long as we are CommonJS, this should be defined + if (require.main) { + packageJsonPath = dirname(require.main.filename) + "/package.json"; + if (existsSync(packageJsonPath)) { + // Throw an error if package.json exists in the main module dir, since we don't want to overwrite or delete it. + // Let the user decide if it is test data, and delete it if it is left over from a previous test. + throw Error("Package JSON exists at " + packageJsonPath + ". Verify the file is test data and delete if it is."); + } + } afterAll(() => { - // eslint-disable-next-line deprecation/deprecation - process.mainModule = mainModule; T.unlinkSync(packageJsonPath); }); - it("We should be able to load our configuration from our package.json", function () { + it("We should be able to load our configuration from our package.json", async function () { const config: IImperativeConfig = { definitions: [ { @@ -48,10 +46,9 @@ describe("Imperative should validate config provided by the consumer", function rootCommandDescription: "My Product CLI" }; T.writeFileSync(packageJsonPath, JSON.stringify({imperative: config, name: "sample"})); - return Imperative.init().then(() => { - // "Display name should have matched our config" - expect(ImperativeConfig.instance.loadedConfig.productDisplayName) - .toEqual(config.productDisplayName); - }); + await Imperative.init(); + + // "Display name should have matched our config" + expect(ImperativeConfig.instance.loadedConfig.productDisplayName).toEqual(config.productDisplayName); }); }); diff --git a/packages/imperative/__tests__/src/packages/imperative/__integration__/PluginManagementFacility.integration.subtest.ts b/packages/imperative/__tests__/src/packages/imperative/__integration__/PluginManagementFacility.integration.subtest.ts index 62e14fc916..f3d91af151 100644 --- a/packages/imperative/__tests__/src/packages/imperative/__integration__/PluginManagementFacility.integration.subtest.ts +++ b/packages/imperative/__tests__/src/packages/imperative/__integration__/PluginManagementFacility.integration.subtest.ts @@ -13,12 +13,14 @@ import { IO } from "../../../../../src/io"; import * as T from "../../../TestUtil"; import { join } from "path"; import { config } from "../plugins/PluginTestConstants"; +import * as Module from "module"; const testCliNodeModulePath = join(__dirname, "..", "plugins", "test_cli", "node_modules"); const impLibDir = join(__dirname, "../../../../../lib"); describe("Plugin Management Facility", () => { const home = config.defaultHome; + const origRequire = Module.prototype.require; beforeAll(() => { /** @@ -44,6 +46,8 @@ describe("Plugin Management Facility", () => { }); afterAll(() => { + // reset require mock to avoid impacting other tests + Module.prototype.require = origRequire; // remove the subdirectories and symbolic link that we created IO.deleteDirTree(testCliNodeModulePath); }); diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/suites/InstallingPlugins.ts b/packages/imperative/__tests__/src/packages/imperative/plugins/suites/InstallingPlugins.ts index 119fe3ba32..c1e6c22702 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/suites/InstallingPlugins.ts +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/suites/InstallingPlugins.ts @@ -83,7 +83,7 @@ describe("Installing Plugins", () => { name: "override-plugin", usage: "override-plugin" }, - registry: { + location: { location: "imperative-sample-plugin", name: "imperative-sample-plugin", usage: "sample-plugin" @@ -256,7 +256,7 @@ describe("Installing Plugins", () => { } const strippedOutput = T.stripNewLines(result.stdout); - expect(strippedOutput).toContain("Registry = " + envNpmRegistry); + expect(strippedOutput).toContain("Location = " + plugins.normal.location); expect(strippedOutput).toContain(`Installed plugin name = '${plugins.normal.name}'`); // Now verify that it got added to the tree @@ -387,7 +387,7 @@ describe("Installing Plugins", () => { setCurrCredMgr(defaultCredMgrDisplayNm); const strippedOutput = T.stripNewLines(result.stdout); - expect(strippedOutput).toContain("Registry = " + envNpmRegistry); + expect(strippedOutput).toContain("Location = " + plugins.override.location); expect(strippedOutput).toContain(`Installed plugin name = '${plugins.override.name}'`); // confirm it was installed @@ -417,7 +417,7 @@ describe("Installing Plugins", () => { } const strippedOutput = T.stripNewLines(result.stdout); - expect(strippedOutput).toContain("Registry = " + TEST_REGISTRY); + expect(strippedOutput).toContain("Location = " + TEST_REGISTRY); expect(strippedOutput).toContain(`Installed plugin name = '${plugins.normal.name}'`); expect(strippedOutput).toContain(`Installed plugin name = '${plugins.normal2.name}'`); @@ -443,7 +443,7 @@ describe("Installing Plugins", () => { } let strippedOutput = T.stripNewLines(result.stdout); - expect(strippedOutput).toContain("Registry = " + envNpmRegistry); + expect(strippedOutput).toContain("Location = " + plugins.normal.location); expect(strippedOutput).toContain(`Installed plugin name = '${plugins.normal.name}'`); const afterInstall = executeCommandString(this, "--help"); @@ -466,7 +466,7 @@ describe("Installing Plugins", () => { } strippedOutput = T.stripNewLines(result.stdout); - expect(strippedOutput).toContain("Registry = " + envNpmRegistry); + expect(strippedOutput).toContain("Location = " + plugins.normal.location); expect(strippedOutput).toContain(`Installed plugin name = '${plugins.normal.name}'`); result = executeCommandString(this, "--help"); @@ -492,7 +492,7 @@ describe("Installing Plugins", () => { } const strippedOutput = T.stripNewLines(result.stdout); - expect(strippedOutput).toContain("Registry = " + envNpmRegistry); + expect(strippedOutput).toContain("Location = " + plugins.space_in_path.location); expect(strippedOutput).toContain(`Installed plugin name = '${plugins.space_in_path.name}'`); // Now verify that it got added to the tree @@ -618,7 +618,7 @@ describe("Installing Plugins", () => { }, [plugins.normal2.name]: { package: plugins.normal2.location, - registry: TEST_REGISTRY, + location: TEST_REGISTRY, version: "1.0.2" }, }; @@ -667,7 +667,7 @@ describe("Installing Plugins", () => { const savedPluginJson = readFileSync(pluginJsonLocation); const expectedContent: IPluginJson = fileContent as IPluginJson; - expectedContent[plugins.normal.name].registry = envNpmRegistry; + expectedContent[plugins.normal.name].location = envNpmRegistry; expect(savedPluginJson).toEqual(expectedContent); }); @@ -735,12 +735,12 @@ describe("Installing Plugins", () => { const actualJson = readFileSync(pluginJsonLocation); // Add missing registry to expected - expectedJson[plugins.normal.name].registry = envNpmRegistry; + expectedJson[plugins.normal.name].location = envNpmRegistry; // Add missing normal2 plugin not present in before each expectedJson[plugins.normal3.name] = { package: plugins.normal3.location, - registry: TEST_REGISTRY, + location: TEST_REGISTRY, version: "1.0.3" }; @@ -751,7 +751,7 @@ describe("Installing Plugins", () => { it("should error when a package and --file is specified", function () { expect( T.stripNewLines( - executeCommandString(this, `${pluginGroup} install ${plugins.registry.location} --file ${testFile}`).stderr + executeCommandString(this, `${pluginGroup} install ${plugins.location.location} --file ${testFile}`).stderr ) ).toContain("Option --file can not be specified if positional package... is as well. They are mutually exclusive."); }); @@ -760,7 +760,7 @@ describe("Installing Plugins", () => { expect( T.stripNewLines( executeCommandString(this, - `${pluginGroup} install ${plugins.registry.location} --file ${testFile} --registry ${TEST_REGISTRY}`).stderr + `${pluginGroup} install ${plugins.location.location} --file ${testFile} --registry ${TEST_REGISTRY}`).stderr ) ).toContain("The following options conflict (mutually exclusive)"); }); diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/suites/ListPlugins.ts b/packages/imperative/__tests__/src/packages/imperative/plugins/suites/ListPlugins.ts index 6ee64c5b66..be2a3ef6cb 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/suites/ListPlugins.ts +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/suites/ListPlugins.ts @@ -28,7 +28,7 @@ describe("List plugin", () => { expect(result.stdout).toContain(`pluginName: ${pluginName}`); expect(result.stdout).toContain(`package:`); expect(result.stdout).toContain(`version:`); - expect(result.stdout).toContain(`registry:`); + expect(result.stdout).toContain(`location:`); }); it("should display proper message when no plugin is installed", () => { diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/suites/UsingPlugins.ts b/packages/imperative/__tests__/src/packages/imperative/plugins/suites/UsingPlugins.ts index 87cc56d325..b39bbaf554 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/suites/UsingPlugins.ts +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/suites/UsingPlugins.ts @@ -30,12 +30,6 @@ describe("Using a Plugin", () => { */ const pluginJsonFile = join(config.defaultHome, "plugins", "plugins.json"); - /** - * Location of the profiles created for test plugins - * @type {string} - */ - const pluginProfDir = join(config.defaultHome, "profiles"); - /** * Specifies whether warnings about missing peer dependencies should be * expected in stderr output of `npm install`. This defaults to true and is @@ -51,7 +45,6 @@ describe("Using a Plugin", () => { beforeEach(() => { // ensure that each test starts with no installed plugins T.rimraf(pluginJsonFile); - T.rimraf(pluginProfDir); }); it("should create plugin commands from in-line JSON text", () => { @@ -138,30 +131,32 @@ describe("Using a Plugin", () => { expect(result.stdout).toContain("globcmd1 First command created by globs"); expect(result.stdout).toContain("globcmd2 Second command created by globs"); - cmd = "profiles list"; + cmd = "config init --global-config"; result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); expect(result.stderr).toBe(""); - expect(result.stdout).toContain("bar-profiles | bar"); - expect(result.stdout).toContain("foo-profiles | foo"); + expect(result.stdout).toContain(`Saved config template to ${config.defaultHome}`); + expect(result.stdout).toContain("plugins_test.config.json"); + + cmd = "config list"; + result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); + expect(result.stderr).toBe(""); + expect(result.stdout).toContain("foo:"); + expect(result.stdout).toContain("type: foo"); + expect(result.stdout).toContain("bar:"); + expect(result.stdout).toContain("type: bar"); cmd = pluginName + " foo"; result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toContain("Command Preparation Failed:"); - expect(result.stderr).toContain("No default profile set for type \"foo\""); + expect(result.stderr).toBe(""); + expect(result.stdout).toContain("You executed the Foo command with size = undefined and duration = undefined"); - cmd = "profiles create foo myFooProfile --duration 5"; + cmd = "config set profiles.foo.properties.size small --global-config"; result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toContain("command 'profiles create foo' is deprecated"); - expect(result.stdout).toContain("Profile created successfully!"); - expect(result.stdout.replace(/\s+/g, " ")).toContain("size: small"); - expect(result.stdout.replace(/\s+/g, " ")).toContain("duration: 5"); + expect(result.stderr).toBe(""); - cmd = "profiles validate foo-profile"; + cmd = "config set profiles.foo.properties.duration 5 --global-config"; result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toContain("command 'profiles validate foo-profile' is deprecated"); - expect(result.stdout).toContain("Check the size of the Foo"); - expect(result.stdout).toContain("Repair in time"); - expect(result.stdout).toContain("Of 2 tests, 2 succeeded, 0 failed, and 0 had warnings or undetermined results."); + expect(result.stderr).toBe(""); cmd = pluginName + " foo"; result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); @@ -245,7 +240,7 @@ describe("Using a Plugin", () => { expect(result.stdout).toContain(`${randomTest}: Messages logged successfully to the following locations`); // Check imperative logger - const impLogLocation = join(config.defaultHome, "imperative", "logs", "imperative.log"); + const impLogLocation = join(config.defaultHome, "logs", "imperative.log"); const impLogContent = readFileSync(impLogLocation).toString(); expect(result.stdout).toContain(resolve(impLogLocation)); expect(impLogContent).not.toContain(`Log message from test plugin: DEBUG: ${randomTest}`); @@ -254,7 +249,7 @@ describe("Using a Plugin", () => { expect(impLogContent).toContain(`Log message from test plugin: ERROR: ${randomTest}`); // Check App/Plugin logger - const appLogLocation = join(config.defaultHome, config.name, "logs", config.name + ".log"); + const appLogLocation = join(config.defaultHome, "logs", config.name + ".log"); const appLogContent = readFileSync(appLogLocation).toString(); expect(result.stdout).toContain(resolve(appLogLocation)); expect(appLogContent).not.toContain(`Log message from test plugin: DEBUG: ${randomTest}`); @@ -297,12 +292,18 @@ describe("Using a Plugin", () => { const knownOverridePluginNm = CredentialManagerOverride.getKnownCredMgrs()[1].credMgrDisplayName as string; setCredMgrOverride(knownOverridePluginNm); - // Create a zosmf profile. That will trigger the CredMgr. - cmd = "profiles create secure-pass-profile TestProfileName --password 'AnyPass' --overwrite"; + /* config init will add the secure-pass profile for the newly installed override-plugin. + * It will also trigger the CredMgr. + */ + cmd = "config init --global-config"; result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toContain("command 'profiles create secure-pass-profile' is deprecated"); + expect(result.stderr).toBe(""); expect(result.stdout).toContain("CredentialManager in sample-plugin is saving these creds:"); - expect(result.stdout).toContain(`password: managed by ${knownOverridePluginNm}`); + expect(result.stdout).toContain("service = plugins_test"); + expect(result.stdout).toContain("account = secure_config_props"); + expect(result.stdout).toContain("credentials = "); + expect(result.stdout).toContain(`Saved config template to ${config.defaultHome}`); + expect(result.stdout).toContain("plugins_test.config.json"); // Restore our name and remove our lifecycle class from package.json pkgContents = fsExtra.readJsonSync(pkgFileNm); diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/suites/ValidatePlugin.ts b/packages/imperative/__tests__/src/packages/imperative/plugins/suites/ValidatePlugin.ts index 2d1a783602..ebabe2e4f9 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/suites/ValidatePlugin.ts +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/suites/ValidatePlugin.ts @@ -247,88 +247,6 @@ describe("Validate plugin", () => { expect(result.status).toEqual(1); }); - // TODO: remove this test in V3, when pluginHealthCheck is removed - it("missing pluginHealthCheck property", () => { - const testPlugin = "missing_pluginHealthCheck"; - const fullPluginPath = join(testPluginDir, "error_plugins", testPlugin); - - let cmd = `plugins install ${fullPluginPath}`; - let result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stdout).toContain(`Installed plugin name = '${testPlugin}'`); - - cmd = `plugins validate ${testPlugin}`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - result.stderr = removeNewline(result.stderr); - expect(result.stdout).toContain(testPlugin); - expect(result.stdout).toContain("This plugin was successfully validated. Enjoy the plugin."); - expect(result.stdout).not.toContain("Warning"); - expect(result.stdout).not.toContain("The plugin's configuration does not contain an 'imperative.pluginHealthCheck' property."); - expect(result.stderr).not.toContain("Problems detected during plugin validation."); - expect(result.status).toEqual(0); - }); - - // TODO: remove this test in V3, when pluginHealthCheck is removed - it("missing pluginHealthCheck property - warning", () => { - const testPlugin = "missing_pluginHealthCheck"; - const fullPluginPath = join(testPluginDir, "error_plugins", testPlugin); - - let cmd = `plugins install ${fullPluginPath}`; - let result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stdout).toContain(`Installed plugin name = '${testPlugin}'`); - - cmd = `plugins validate ${testPlugin} --fail-on-warning`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - result.stderr = removeNewline(result.stderr); - expect(result.stdout).toContain(testPlugin); - expect(result.stdout).toContain("This plugin was successfully validated. Enjoy the plugin."); - expect(result.stdout).not.toContain("Warning"); - expect(result.stdout).not.toContain("The plugin's configuration does not contain an 'imperative.pluginHealthCheck' property."); - expect(result.stderr).not.toContain("Problems detected during plugin validation."); - expect(result.status).toEqual(0); - }); - - // TODO: remove this test in V3, when pluginHealthCheck is removed - it("missing pluginHealthCheck handler", () => { - const testPlugin = "missing_healthcheck_handler"; - const fullPluginPath = join(testPluginDir, "error_plugins", testPlugin); - - let cmd = `plugins install ${fullPluginPath}`; - let result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stdout).toContain(`Installed plugin name = '${testPlugin}'`); - - cmd = `plugins validate ${testPlugin} --no-fail-on-error`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - result.stderr = removeNewline(result.stderr); - expect(result.stdout).toContain(testPlugin); - expect(result.stdout).toContain("This plugin was successfully validated. Enjoy the plugin."); - expect(result.stdout).not.toContain("Error"); - expect(result.stdout).not.toContain(`The program for the 'imperative.pluginHealthCheck' property does not exist:`); - expect(result.stdout).not.toContain("This plugin has configuration errors. No component of the plugin will be available"); - expect(result.stderr).not.toContain("Problems detected during plugin validation."); - expect(result.status).toEqual(0); - }); - - // TODO: remove this test in V3, when pluginHealthCheck is removed - it("missing pluginHealthCheck handler - error", () => { - const testPlugin = "missing_healthcheck_handler"; - const fullPluginPath = join(testPluginDir, "error_plugins", testPlugin); - - let cmd = `plugins install ${fullPluginPath}`; - let result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stdout).toContain(`Installed plugin name = '${testPlugin}'`); - - cmd = `plugins validate ${testPlugin}`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - result.stderr = removeNewline(result.stderr); - expect(result.stdout).toContain(testPlugin); - expect(result.stdout).toContain("This plugin was successfully validated. Enjoy the plugin."); - expect(result.stdout).not.toContain("Error"); - expect(result.stdout).not.toContain(`The program for the 'imperative.pluginHealthCheck' property does not exist:`); - expect(result.stdout).not.toContain("This plugin has configuration errors. No component of the plugin will be available"); - expect(result.stderr).not.toContain("Problems detected during plugin validation."); - expect(result.status).toEqual(0); - }); - it("missing peerDependencies properties", () => { const testPlugin = "missing_dependencies"; const fullPluginPath = join(testPluginDir, "error_plugins", testPlugin); diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/chained_handler_plugin/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/chained_handler_plugin/package.json index 2d9511a451..a4462c7dbf 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/chained_handler_plugin/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/chained_handler_plugin/package.json @@ -10,7 +10,6 @@ "name": "chained-handler-plugin", "rootCommandDescription": "imperative working test plugin", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./lib/sample-plugin/healthCheck.handler", "pluginAliases": [ "chp", "chainedhandlerp" diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_bad_chained_handler/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_bad_chained_handler/package.json index dfccfd6f96..a593717a78 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_bad_chained_handler/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_bad_chained_handler/package.json @@ -10,7 +10,6 @@ "name": "definition_bad_chained_handler", "rootCommandDescription": "definition bad chained handler", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./dummy.handler", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_empty_array/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_empty_array/package.json index 94b70a1436..1f93016c2c 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_empty_array/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_empty_array/package.json @@ -10,7 +10,6 @@ "name": "definition_empty_array", "rootCommandDescription": "definition empty array", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./dummy.handler", "definitions": [] }, "peerDependencies": { diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_empty_chained_handler/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_empty_chained_handler/package.json index fce6748813..24b3cee220 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_empty_chained_handler/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_empty_chained_handler/package.json @@ -10,7 +10,6 @@ "name": "definition_empty_chained_handler", "rootCommandDescription": "definition empty chained handler", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./dummy.handler", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_chained_handler/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_chained_handler/package.json index ac0e30bbce..3b7c3159a6 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_chained_handler/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_chained_handler/package.json @@ -10,7 +10,6 @@ "name": "definition_missing_chained_handler", "rootCommandDescription": "definition missing chained handler", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./dummy.handler", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_description/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_description/package.json index 7803fc1414..cebf44fa68 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_description/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_description/package.json @@ -10,7 +10,6 @@ "name": "definition_missing_description", "rootCommandDescription": "definition missing description", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./dummy.handler", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_handler/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_handler/package.json index fd6d54799f..727095a570 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_handler/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_handler/package.json @@ -10,7 +10,6 @@ "name": "definition_missing_handler", "rootCommandDescription": "definition missing handler", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./dummy.handler", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_name/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_name/package.json index f2497789d1..5723e42824 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_name/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_name/package.json @@ -10,7 +10,6 @@ "name": "definition_missing_name", "rootCommandDescription": "definition missing name", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./dummy.handler", "definitions": [ { "description": "dummy foo command", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_type/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_type/package.json index 234197b925..63a75dfdc5 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_type/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_missing_type/package.json @@ -10,7 +10,6 @@ "name": "definition_missing_type", "rootCommandDescription": "definition missing type", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./dummy.handler", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_type_group_without_children/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_type_group_without_children/package.json index 288f7480b5..2ed5d77f7e 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_type_group_without_children/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/definition_type_group_without_children/package.json @@ -10,7 +10,6 @@ "name": "definition_type_group_without_children", "rootCommandDescription": "definition type group without children", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./dummy.handler", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/duplicated_base_cli_command/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/duplicated_base_cli_command/package.json index ea2957c5bd..4d67859119 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/duplicated_base_cli_command/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/duplicated_base_cli_command/package.json @@ -10,7 +10,6 @@ "name": "plugins", "rootCommandDescription": "duplicated base cli command", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./dummy.handler", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/duplicated_installed_plugin_command/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/duplicated_installed_plugin_command/package.json index 71f37ceb63..6d13183e88 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/duplicated_installed_plugin_command/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/duplicated_installed_plugin_command/package.json @@ -10,7 +10,6 @@ "name": "normal-plugin", "rootCommandDescription": "duplicated installed plugin command", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./dummy.handler", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/incompatible_imperative_version/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/incompatible_imperative_version/package.json index c7bab7c1b5..3dbbd6445d 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/incompatible_imperative_version/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/incompatible_imperative_version/package.json @@ -10,7 +10,6 @@ "name": "incompatible_imperative_version", "rootCommandDescription": "imperative working test plugin", "pluginBaseCliVersion": "^2.0.0", - "pluginHealthCheck": "./dummy.handler", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_command_handler/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_command_handler/package.json index 45fa443285..95f46c2ae8 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_command_handler/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_command_handler/package.json @@ -10,7 +10,6 @@ "name": "missing_command_handler", "rootCommandDescription": "imperative working test plugin", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./dummy.handler", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_definitions/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_definitions/package.json index 6ce9a4fc41..5fde89a050 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_definitions/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_definitions/package.json @@ -9,8 +9,7 @@ "imperative": { "name": "missing_definitions", "rootCommandDescription": "missing definitions", - "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./dummy.handler" + "pluginBaseCliVersion": "^1.0.0" }, "peerDependencies": { "@zowe/imperative": "1.0.0" diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_dependencies/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_dependencies/package.json index f619e6306e..80f9528f1d 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_dependencies/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_dependencies/package.json @@ -10,7 +10,6 @@ "name": "missing_dependencies", "rootCommandDescription": "imperative working test plugin", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./dummy.handler", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_healthcheck_handler/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_healthcheck_handler/package.json index a9cfb8489c..5c5b588152 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_healthcheck_handler/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_healthcheck_handler/package.json @@ -10,7 +10,6 @@ "name": "missing_healthcheck_handler", "rootCommandDescription": "imperative working test plugin", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./non_existing_path", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_pluginBaseCliVersion/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_pluginBaseCliVersion/package.json index e0edb6227b..0db2951d39 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_pluginBaseCliVersion/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_pluginBaseCliVersion/package.json @@ -9,7 +9,6 @@ "imperative": { "name": "missing_pluginBaseCliVersion", "rootCommandDescription": "imperative working test plugin", - "pluginHealthCheck": "./dummy.handler", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_pluginHealthCheck/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_pluginHealthCheck/package.json deleted file mode 100644 index 07c75dba63..0000000000 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_pluginHealthCheck/package.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "missing_pluginHealthCheck", - "version": "1.0.1", - "description": "Some description", - "main": "../lib/index.js", - "files": [ - "lib" - ], - "imperative": { - "name": "missing_pluginHealthCheck", - "rootCommandDescription": "imperative working test plugin", - "pluginBaseCliVersion": "^1.0.0", - "definitions": [ - { - "name": "foo", - "description": "dummy foo command", - "type": "command", - "handler": "./dummy.handler" - }, - { - "name": "bar", - "description": "dummy bar command", - "type": "command", - "handler": "./dummy.handler" - } - ] - }, - "peerDependencies": { - "@zowe/imperative": "1.0.0" - }, - "typings": "lib/index.d.ts", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "EPL 2.0", - "private": false, - "publishConfig": { - "registry": "http://imperative-npm-registry:4873" - } -} diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_rootCommandDescription/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_rootCommandDescription/package.json index 5dcfae10ca..8b8de2ca07 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_rootCommandDescription/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_rootCommandDescription/package.json @@ -9,7 +9,6 @@ "imperative": { "name": "missing_rootCommandDescription", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./dummy.handler", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/profile_dup_in_plugin/configuration.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/profile_dup_in_plugin/configuration.js index ac1ba1c267..44a7331899 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/profile_dup_in_plugin/configuration.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/profile_dup_in_plugin/configuration.js @@ -28,7 +28,6 @@ const config = { } } ], - pluginHealthCheck: "./healthCheck.handler", rootCommandDescription: "Test plugin with profiles", pluginBaseCliVersion: "^1.0.0", defaultHome: "../../../../../../__results__/.pluginstest", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/profile_dup_with_cli/configuration.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/profile_dup_with_cli/configuration.js index 4cf6d9c949..cdb7189b84 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/profile_dup_with_cli/configuration.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/profile_dup_with_cli/configuration.js @@ -27,7 +27,6 @@ const config = { } } ], - pluginHealthCheck: "./healthCheck.handler", rootCommandDescription: "Test plugin with profiles", pluginBaseCliVersion: "^1.0.0", defaultHome: "../../../../../../__results__/.pluginstest", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/missing_name_plugin/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/missing_name_plugin/package.json index 65b16b3f39..5b3a578e38 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/missing_name_plugin/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/missing_name_plugin/package.json @@ -9,7 +9,6 @@ "imperative": { "rootCommandDescription": "missing name plugin", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./dummy.handler", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin/package.json index d7a7584112..1525fe3e5c 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin/package.json @@ -10,7 +10,6 @@ "name": "normal-plugin", "rootCommandDescription": "imperative working test plugin", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./lib/sample-plugin/healthCheck.handler", "pluginAliases": [ "np", "normalp" diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_2/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_2/package.json index 26af69aec4..881151fbb2 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_2/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_2/package.json @@ -10,7 +10,6 @@ "name": "normal-plugin-2", "rootCommandDescription": "imperative working test plugin 2", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./lib/sample-plugin/healthCheck.handler", "definitions": [ { "name": "foo", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/foo/foo.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/foo/foo.handler.js index 32459f2b30..f1a6189871 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/foo/foo.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/cmd/foo/foo.handler.js @@ -8,15 +8,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; Object.defineProperty(exports, "__esModule", { value: true }); -// const imperative_cli_1 = require("imperative"); +const imperative_cli_1 = require("@zowe/imperative"); class FooHandler { process(params) { return __awaiter(this, void 0, void 0, function* () { - // const impFileLogger = imperative_cli_1.Logger.getImperativeLogger(); - const profile = params.profiles.get("foo"); + const profile = imperative_cli_1.ImperativeConfig.instance.config.api.profiles.get("foo"); const successMsg = "You executed the Foo command with size = " + profile.size + " and duration = " + profile.duration; - // impFileLogger.debug(successMsg); params.response.console.log(successMsg); yield undefined; }); diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/configuration.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/configuration.js index f336c1c779..c8d906695c 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/configuration.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_3/lib/sample-plugin/configuration.js @@ -26,7 +26,6 @@ const config = { } } ], - pluginHealthCheck: "./lib/sample-plugin/healthCheck.handler", commandModuleGlobs: ["**/cmd/*/*.definition!(.d).*s"], rootCommandDescription: "Test plugin with globs and profiles", pluginBaseCliVersion: "^0.4.0-1", diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/cmd/imperative-logging/imperativeLogging.handler.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/cmd/imperative-logging/imperativeLogging.handler.js index 8ae0fe9225..9e937b6e98 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/cmd/imperative-logging/imperativeLogging.handler.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/lib/sample-plugin/cmd/imperative-logging/imperativeLogging.handler.js @@ -31,8 +31,8 @@ class ImperativeLoggingHandler { var config = T.ImperativeConfig.instance.loadedConfig; params.response.console.log(`${params.arguments.test}: Messages logged successfully to the following locations`); - params.response.console.log(path.join(config.defaultHome, "imperative", "logs", "imperative.log")); - params.response.console.log(path.join(config.defaultHome, config.name, "logs", config.name + ".log")); + params.response.console.log(path.join(config.defaultHome, "logs", "imperative.log")); + params.response.console.log(path.join(config.defaultHome, "logs", config.name + ".log")); yield undefined; }); } diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/package.json index 8cec963ec8..9395b56f88 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/normal_plugin_misc/package.json @@ -10,7 +10,6 @@ "name": "normal-plugin-misc", "rootCommandDescription": "imperative working test plugin", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./lib/sample-plugin/healthCheck.handler", "pluginAliases": [ "misc" ], diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/overrides/CredentialManager.override.js b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/overrides/CredentialManager.override.js index f4a29aeb51..23cae86596 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/overrides/CredentialManager.override.js +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/lib/sample-plugin/overrides/CredentialManager.override.js @@ -43,7 +43,7 @@ module.exports = class CredentialManagerOverrides extends imperative_1.AbstractC failNotFound: true }; const loadResultString = JSON.stringify(loadedProfResult, null, 2); - yield Buffer.from(loadResultString).toString("base64"); + return Buffer.from(loadResultString).toString("base64"); }); } saveCredentials(account, credentials) { diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/package.json index e91c6c1b6f..8851951c26 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/override_plugin/package.json @@ -10,7 +10,6 @@ "name": "override-plugin", "rootCommandDescription": "imperative override plugin rootCommandDescription", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./lib/sample-plugin/healthCheck.handler", "overrides": { "CredentialManager": "./sample-plugin/overrides/CredentialManager.override" }, diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/space in path plugin/package.json b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/space in path plugin/package.json index f731d2cd82..20f717eb7d 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/space in path plugin/package.json +++ b/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/space in path plugin/package.json @@ -10,7 +10,6 @@ "name": "space-in-path-plugin", "rootCommandDescription": "imperative working test plugin", "pluginBaseCliVersion": "^1.0.0", - "pluginHealthCheck": "./lib/sample-plugin/healthCheck.handler", "pluginAliases": [ "np", "normalp" diff --git a/packages/imperative/__tests__/src/packages/profiles/__integration__/BasicProfileManager.initialize.integration.test.ts b/packages/imperative/__tests__/src/packages/profiles/__integration__/BasicProfileManager.initialize.integration.test.ts deleted file mode 100644 index 3d2ae4b317..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/__integration__/BasicProfileManager.initialize.integration.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -jest.mock("../../../../../src/utilities/src/ImperativeConfig"); - -import * as TestUtil from "../../../TestUtil"; -import { BasicProfileManager } from "../../../../../src/index"; -import { TestLogger } from "../../../../src/TestLogger"; -import { PROFILE_TYPE, getConfig } from "../src/constants/BasicProfileManagerTestConstants"; -import * as fs from "fs"; - -const profileDirectory = TestUtil.createUniqueTestDataDir("profile-manager-initialize"); - -describe("Basic Profile Manager Initialize", () => { - it("Should allow us to initialize the environment and create a profile manager", async () => { - const config = getConfig(profileDirectory); - - const responses = BasicProfileManager.initialize({ - configuration: config.profiles, - profileRootDirectory: profileDirectory - }); - try { - // Ensure the type directories created - const dirs = fs.readdirSync(profileDirectory); - const profTypes = Object.keys(PROFILE_TYPE).sort().map((keyType: string): string => keyType.toLocaleLowerCase()); - - expect(dirs).toEqual(profTypes); - - for (let i = 0; i < dirs.length; i++) { - // Ensure that the directories contain the meta files - const profDir = fs.readdirSync(profileDirectory + "/" + dirs[i]); - expect(profDir).toEqual([profTypes[i] + "_meta.yaml"]); - - const profMeta = fs.readFileSync(profileDirectory + "/" + dirs[i] + "/" + profDir[0]).toString(); - expect(profMeta).toMatchSnapshot(); - } - - // Create a manager instance - const manager = new BasicProfileManager({ - profileRootDirectory: profileDirectory, - logger: TestLogger.getTestLogger(), - type: PROFILE_TYPE.BANANA - }); - } catch (e) { - TestLogger.error(e); - throw e; - } - }); -}); diff --git a/packages/imperative/__tests__/src/packages/profiles/__integration__/BasicProfileManager.integration.test.ts b/packages/imperative/__tests__/src/packages/profiles/__integration__/BasicProfileManager.integration.test.ts deleted file mode 100644 index 20119d45c4..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/__integration__/BasicProfileManager.integration.test.ts +++ /dev/null @@ -1,138 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import * as TestUtil from "../../../TestUtil"; -import { inspect } from "util"; -import { TestLogger } from "../../../../src/TestLogger"; -import { ProfileUtils } from "../../../../../src/profiles"; -import { BANANA_AGE, getConfig, PROFILE_TYPE } from "../src/constants/BasicProfileManagerTestConstants"; - -describe("Imperative should allow CLI implementations to configure their own profiles and types", function () { - // eslint-disable-next-line deprecation/deprecation - const mainModule = process.mainModule; - const loadChangingDependencies = () => { - return { - Imperative: require("../../../../../src/imperative/src/Imperative").Imperative, - ImperativeConfig: require("../../../../../src/utilities/src/ImperativeConfig").ImperativeConfig, - ImperativeError: require("../../../../../src/error/src/ImperativeError").ImperativeError - }; - }; - - let {Imperative, ImperativeError, ImperativeConfig} = loadChangingDependencies(); - - // Initialize imperative before each test - beforeEach(() => { - jest.resetModules(); - ({Imperative, ImperativeError, ImperativeConfig} = loadChangingDependencies()); - }); - - beforeAll(() => { - // eslint-disable-next-line deprecation/deprecation - (process.mainModule as any) = { - filename: __filename - }; - }); - - afterAll(() => { - // eslint-disable-next-line deprecation/deprecation - process.mainModule = mainModule; - }); - - it("should be able to create a profile type and retrieve all defined types after init", async function () { - const config = getConfig(TestUtil.createUniqueTestDataDir("profile-manager-initialize")); - await Imperative.init(config); - expect(ProfileUtils.getAllTypeNames(ImperativeConfig.instance.loadedConfig.profiles).length).toEqual(Object.keys(PROFILE_TYPE).length); - expect(ProfileUtils.getAllTypeNames(ImperativeConfig.instance.loadedConfig.profiles)).toContain("banana"); - }); - - it("should be receive a failure message when attempting to load a profile that doesn't exist", async function () { - const config = getConfig(TestUtil.createUniqueTestDataDir("profile-manager-initialize")); - await Imperative.init(config); - let error; - try { - const response = await Imperative.api.profileManager("banana").load({name: "notreal"}); - TestLogger.info(response.message); - } catch (e) { - error = e; - TestLogger.info(error.message); - } - expect(error).toBeInstanceOf(ImperativeError); - }); - - it("should receive a failure message when attempting to create an ill-formed profile", async function () { - const config = getConfig(TestUtil.createUniqueTestDataDir("profile-manager-initialize")); - await Imperative.init(config); - let error; - try { - const response = await Imperative.api.profileManager("banana").save({ - name: "illformed", - profile: { - fail: "this" - } - }); - TestLogger.info(response.message); - } catch (e) { - error = e; - TestLogger.info(error.message); - } - expect(error).toBeInstanceOf(ImperativeError); - }); - - it("should be able to create a basic profile", async function () { - const config = getConfig(TestUtil.createUniqueTestDataDir("profile-manager-initialize")); - await Imperative.init(config); - const response = await Imperative.api.profileManager("banana").save({ - name: "legit", - profile: { - age: BANANA_AGE - } - }); - TestLogger.info(`Profile create success response: ${inspect(response, {depth: null})}`); - expect(response.message).toContain(`Profile ("legit" of type "banana") successfully written:`); - expect(response.overwritten).toEqual(false); - expect(response.path).toContain("legit.yaml"); - }); - - it("should be able to create a basic profile and load that profile", async function () { - const config = getConfig(TestUtil.createUniqueTestDataDir("profile-manager-initialize")); - await Imperative.init(config); - const saveResponse = await Imperative.api.profileManager("banana").save({ - name: "legit", - profile: {age: BANANA_AGE}, - overwrite: true, - updateDefault: true - }); - - TestLogger.info("Save response: " + saveResponse.message); - const loadResponse = await Imperative.api.profileManager("banana").load({name: "legit"}); - TestLogger.info(`Profile loaded success response: ${inspect(loadResponse, {depth: null})}`); - expect(loadResponse.name).toEqual("legit"); - expect(loadResponse.type).toEqual("banana"); - expect(loadResponse.profile).toBeDefined(); - expect(loadResponse.profile).toMatchSnapshot(); - }); - - it("should be able to create a basic profile and load as the default", async function () { - const config = getConfig(TestUtil.createUniqueTestDataDir("profile-manager-initialize")); - await Imperative.init(config); - const response = await Imperative.api.profileManager("banana").save({ - name: "legit", - profile: {age: BANANA_AGE}, - overwrite: true, - updateDefault: true - }); - TestLogger.info(`Profile create success response: ${inspect(response, {depth: null})}`); - const load = await Imperative.api.profileManager("banana").load({loadDefault: true}); - expect(load.type).toEqual("banana"); - expect(load.profile).toBeDefined(); - expect(load.profile).toMatchSnapshot(); - }); -}); diff --git a/packages/imperative/__tests__/src/packages/profiles/__integration__/CliProfileManager.credentials.integration.subtest.ts b/packages/imperative/__tests__/src/packages/profiles/__integration__/CliProfileManager.credentials.integration.subtest.ts deleted file mode 100644 index 4bea3829de..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/__integration__/CliProfileManager.credentials.integration.subtest.ts +++ /dev/null @@ -1,363 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import * as T from "../../../TestUtil"; -import * as path from "path"; -import * as fs from "fs"; -import { IImperativeConfig } from "../../../../../src/imperative"; -import { CliProfileManager } from "../../../../../src/cmd"; -import { ProfileIO } from "../../../../../src/profiles/src/utils"; -import { IProfile } from "../../../../../src/profiles/src/doc/definition"; - -describe("Cli Profile Manager", () => { - let writtenProfile: any; - const credentialManagerErrorMessage = /(Unable to).*(the secure field)/; - - const originalSaveProfile = (CliProfileManager.prototype as any).saveProfile; - afterEach(() => { - (CliProfileManager.prototype as any).saveProfile = originalSaveProfile; - }); - ProfileIO.writeProfile = jest.fn((fullFilePath: string, profile: IProfile) => { - writtenProfile = profile; - }); - - ProfileIO.exists = jest.fn((profilePath: string) => { - return profilePath.indexOf("meta") === -1 ? profilePath : undefined; - }); - - ProfileIO.readMetaFile = jest.fn((fullFilePath: string) => { - return { - defaultProfile: "mybana", - configuration: { - type: "", - schema: { - type: "object", - title: "test profile", - description: "test profile", - properties: { - sum: { - type: "number" - } - }, - required: ["sum"] - } - } - }; - }) as any; - afterEach(() => { - writtenProfile = undefined; // clear any saved profile to not pollute results across tests - }); - - describe("Default Credential Management", () => { - const cliBin = path.join(__dirname, "../test_cli/TestCLI.ts"); - const config: IImperativeConfig = require(path.join(__dirname, "../test_cli/TestConfiguration")); - const homeDir: string = config.defaultHome; - - const testProfileName = "username-password"; - const username: string = "username"; - const password: number = 0; - const account: string = "account123"; - const secured: string = "secured"; - const insecured: string = "insecured"; // playing off insecure child... - const newPass: number = 1; - - beforeEach(() => { - T.rimraf(homeDir); - }); - - describe("Generic Success Scenarios", () => { - const profileName = "profile-name"; - - it("should create and load a profile with saved credentials", () => { - let cmd = `profiles create ${testProfileName}-profile ${profileName} --username ${username} ` + - `--password ${password} --account ${account} --sec1 ${secured} --insec1 ${insecured}`; - let result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - - expect(result.stderr).toContain("command 'profiles create username-password-profile' is deprecated"); - expect(result.stdout).toContain("Profile created successfully!"); - cmd = `display-profile`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toEqual(""); - expect(JSON.parse(result.stdout)).toEqual({ - myParent: { - insecuredProperty: {myInSecuredChild: "insecured"}, - securedProperty: {mySecuredChild: "secured"} - }, - account, username, password}); - }); - - it("should overwrite and load a profile with saved credentials", () => { - let cmd = `profiles create ${testProfileName}-profile ${profileName} --username ${username} ` + - `--password ${password} --account ${account} --sec1 ${secured} --insec1 ${insecured}`; - let result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toContain("command 'profiles create username-password-profile' is deprecated"); - expect(result.stdout).toContain("Profile created successfully!"); - - cmd = `profiles create ${testProfileName}-profile ${profileName} --username ${username} ` + - `--password ${password} --account ${account} --sec1 ${secured} --insec1 ${insecured} --ow`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toContain("command 'profiles create username-password-profile' is deprecated"); - expect(result.stdout).toContain("Overwrote existing profile"); - expect(result.stdout).toContain("Profile created successfully!"); - }); - - it("should update and load a profile with saved credentials", () => { - const newName: string = "newName"; - - let cmd = `profiles create ${testProfileName}-profile ${profileName} --username ${username} ` + - `--password ${password} --account ${account} --sec1 ${secured} --insec1 ${insecured}`; - let result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toContain("command 'profiles create username-password-profile' is deprecated"); - expect(result.stdout).toContain("Profile created successfully!"); - - cmd = `profiles update ${testProfileName}-profile ${profileName} --username ${newName} --password ${newPass}`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toContain("command 'profiles update username-password-profile' is deprecated"); - expect(result.stdout).toContain("Overwrote existing profile"); - expect(result.stdout).toContain("Profile updated successfully!"); - - cmd = `display-profile`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toEqual(""); - expect(JSON.parse(result.stdout)).toEqual({ - myParent: { - insecuredProperty: {myInSecuredChild: "insecured"}, - securedProperty: {mySecuredChild: "secured"} - }, - account, username: newName, password: newPass}); - }); - - it("should delete a profile with saved credentials", () => { - let cmd = `profiles create ${testProfileName}-profile ${profileName} --username ${username} ` + - `--password ${password} --account ${account} --sec1 ${secured} --insec1 ${insecured}`; - let result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toContain("command 'profiles create username-password-profile' is deprecated"); - expect(result.stdout).toContain("Profile created successfully!"); - - cmd = `profiles delete ${testProfileName}-profile ${profileName}`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toContain("command 'profiles delete username-password-profile' is deprecated"); - expect(result.stdout).toContain("successfully deleted"); - }); - - it("should update a password", () => { - let cmd = `profiles create ${testProfileName}-profile ${profileName} --username ${username} ` + - `--password ${password} --account ${account} --sec1 ${secured} --insec1 ${insecured}`; - let result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - - expect(result.stderr).toContain("command 'profiles create username-password-profile' is deprecated"); - expect(result.stdout).toContain("Profile created successfully!"); - - // profiles upd username-password username-password --password pass - cmd = `profiles update ${testProfileName}-profile ${profileName} --password ${newPass}`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - - expect(T.stripNewLines(result.stdout)).toContain("Overwrote existing profile"); - expect(result.stderr).toMatchSnapshot(); - - cmd = `profiles delete ${testProfileName}-profile ${profileName}`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - - expect(result.stderr).toContain("command 'profiles delete username-password-profile' is deprecated"); - expect(T.stripNewLines(result.stdout)).toContain("successfully deleted"); - expect(result.stdout).toMatchSnapshot(); - }); - }); - - describe("Generic Failure Scenarios", () => { - const createdName = "profile-name"; - const changedName = "profile-name-changed"; - const changedProfileName = "changed-username-password"; - - const profilePath = path.join(homeDir, "profiles", testProfileName); - const createdPath = path.join(profilePath, createdName + ".yaml"); - const changedPath = path.join(profilePath, changedName + ".yaml"); - - it("should fail if the Credential Manager is unable to find the profile", () => { - let cmd = `profiles create ${testProfileName}-profile ${createdName} --username ${username} ` + - `--password ${password} --account ${account} --sec1 ${secured} --insec1 ${insecured}`; - let result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - - expect(result.stderr).toContain("command 'profiles create username-password-profile' is deprecated"); - expect(result.stdout).toContain("Profile created successfully!"); - - // Now change the name of the profile so that we can break it - fs.renameSync(createdPath, changedPath); - - cmd = `profiles delete ${testProfileName}-profile ${createdName}`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - - expect(T.stripNewLines(result.stderr)).toContain(`Profile "${createdName}" of type "${testProfileName}" does not exist.`); - expect(result.stderr).toContain("Profile \"profile-name\" of type \"username-password\" does not exist"); - expect(result.stderr).toContain("The command 'profiles delete username-password-profile' is deprecated"); - - // Now put it back for cleanup - fs.renameSync(changedPath, createdPath); - - cmd = `profiles delete ${testProfileName}-profile ${createdName}`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - - expect(result.stderr).toContain("command 'profiles delete username-password-profile' is deprecated"); - expect(T.stripNewLines(result.stdout)).toContain("successfully deleted"); - }); - - it("should fail if the Credential Manager is unable to retrieve a password", () => { - let cmd = `profiles create ${testProfileName}-profile ${createdName} --username ${username} ` + - `--password ${password} --account ${account} --sec1 ${secured} --insec1 ${insecured}`; - let result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - - expect(result.stderr).toContain("command 'profiles create username-password-profile' is deprecated"); - expect(result.stdout).toContain("Profile created successfully!"); - - // Now change the name of the profile so that we can break it - fs.renameSync(createdPath, changedPath); - - cmd = `display-profile --${testProfileName}-profile ${changedName}`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - - expect(T.stripNewLines(result.stderr)).toMatch(credentialManagerErrorMessage); - expect(result.stderr).toMatchSnapshot(); - - // Now put it back for cleanup - fs.renameSync(changedPath, createdPath); - - cmd = `profiles delete ${testProfileName}-profile ${createdName}`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - - expect(result.stderr).toContain("command 'profiles delete username-password-profile' is deprecated"); - expect(T.stripNewLines(result.stdout)).toContain("successfully deleted"); - expect(result.stdout).toMatchSnapshot(); - }); - }); - - describe("Missing keytar installation", () => { - const profileName = "missing-keytar"; - const keyTarDir = path.join(__dirname, "../../../../../../../node_modules/@zowe/secrets-for-zowe-sdk"); - const renamedKeyTarDir = path.join(__dirname, "../../../../../../../node_modules/@zowe/zowe-for-secrets-sdk"); - - const renameKeyTar = () => { - if (fs.existsSync(keyTarDir)) { - fs.renameSync(keyTarDir, renamedKeyTarDir); - } - }; - - // Make sure that the keytar folder is reset to the original name. - afterEach(() => { - if (fs.existsSync(renamedKeyTarDir)) { - fs.renameSync(renamedKeyTarDir, keyTarDir); - } - }); - - it("should fail if keytar is not loaded on profiles create", () => { - renameKeyTar(); - - const cmd = `profiles create ${testProfileName}-profile ${profileName} --username ${username} ` + - `--password ${password} --account ${account} --sec1 ${secured} --insec1 ${insecured}`; - const result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stdout).toEqual(""); - expect(result.stderr).toContain(profileName); - expect(result.stderr).toContain("Failed to load Keytar module"); - }); - - it("should fail if keytar is not loaded on using profile handler", () => { - let cmd = `profiles create ${testProfileName}-profile ${profileName} --username ${username} ` + - `--password ${password} --account ${account} --sec1 ${secured} --insec1 ${insecured}`; - let result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toContain("command 'profiles create username-password-profile' is deprecated"); - expect(result.stdout).toContain("Profile created successfully!"); - - renameKeyTar(); - - cmd = `display-profile`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toContain("Command Preparation Failed"); - expect(result.stderr).toContain("Failed to load Keytar module"); - }); - - it("should fail if keytar is not loaded on profiles delete", () => { - let cmd = `profiles create ${testProfileName}-profile ${profileName} --username ${username} ` + - `--password ${password} --account ${account} --sec1 ${secured} --insec1 ${insecured}`; - let result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toContain("command 'profiles create username-password-profile' is deprecated"); - expect(result.stdout).toContain("Profile created successfully!"); - - renameKeyTar(); - - cmd = `profiles delete ${testProfileName}-profile ${profileName}`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toContain(profileName); - expect(result.stderr).toMatch(credentialManagerErrorMessage); - }); - - it("should be able to issue command", () => { - renameKeyTar(); - - const cmd = `display-non-keytar`; - const result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stdout).toContain("This handler does not require keytar"); - }); - }); - }); - - describe("Custom Credential Management (Absolute String)", () => { - const cliBin = path.join(__dirname, "../test_cli/TestCustomCredString.ts"); - const config: IImperativeConfig = require(path.join(__dirname, "../test_cli/TestCustomCredStringConfiguration")); - const homeDir: string = config.defaultHome; - - const testProfileName = "username-password"; - const username: string = "username"; - const password: string = "password"; - - beforeEach(() => { - T.rimraf(homeDir); - }); - - it("should use an overwritten credential manager (Absolute String)", () => { - const profileName = "custom-credential-string"; - - let cmd = `profiles create ${testProfileName}-profile ${profileName} --username ${username} --password ${password}`; - let result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toContain("command 'profiles create username-password-profile' is deprecated"); - expect(result.stdout).toContain("Profile created successfully!"); - - cmd = `display-profile`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(JSON.parse(result.stdout)).toEqual({username: "custom", password: "custom"}); - }); - }); - - describe("Custom Credential Management (Class)", () => { - const cliBin = path.join(__dirname, "../test_cli/TestCustomCredClass.ts"); - const config: IImperativeConfig = require(path.join(__dirname, "../test_cli/TestCustomCredClassConfiguration")); - const homeDir: string = config.defaultHome; - - const testProfileName = "username-password"; - const username: string = "username"; - const password: string = "password"; - - beforeEach(() => { - T.rimraf(homeDir); - }); - - it("should use an overwritten credential manager (Class)", () => { - const profileName = "custom-credential-class"; - - let cmd = `profiles create ${testProfileName}-profile ${profileName} --username ${username} --password ${password}`; - let result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(result.stderr).toContain("command 'profiles create username-password-profile' is deprecated"); - expect(result.stdout).toContain("Profile created successfully!"); - - cmd = `display-profile`; - result = T.executeTestCLICommand(cliBin, this, cmd.split(" ")); - expect(JSON.parse(result.stdout)).toEqual({ username: "custom", password: "custom"}); - }); - }); -}); diff --git a/packages/imperative/__tests__/src/packages/profiles/__integration__/ProfileCommandExample.integration.test.ts b/packages/imperative/__tests__/src/packages/profiles/__integration__/ProfileCommandExample.integration.test.ts deleted file mode 100644 index 287d3fb8f4..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/__integration__/ProfileCommandExample.integration.test.ts +++ /dev/null @@ -1,134 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import * as T from "../../../TestUtil"; -import { IImperativeConfig } from "../../../../../src/imperative"; -import * as yargs from "yargs"; -import { Constants } from "../../../../../src/constants"; -import { CommandProcessor, ICommandDefinition, ICommandProfileTypeConfiguration, ICommandResponse } from "../../../../../src/cmd"; -import { ICommandProcessorParms } from "../../../../../src/cmd/src/doc/processor/ICommandProcessorParms"; -import { TestLogger } from "../../../../src/TestLogger"; -import { AbstractHelpGenerator } from "../../../../../src/cmd/src/help/abstract/AbstractHelpGenerator"; -import { DefaultHelpGenerator } from "../../../../../src/cmd/src/help/DefaultHelpGenerator"; -import { BasicProfileManagerFactory } from "../../../../../src/index"; - -const logger = TestLogger.getTestLogger(); -const PROFILE_CONFIGURATIONS: ICommandProfileTypeConfiguration[] = [{ - type: "banana", - schema: { - type: "object", - title: "The Banana command profile schema", - description: "The Banana command profile schema", - properties: { - age: { - optionDefinition: { - description: "The age of the Banana", - type: "number", - name: "age", aliases: ["a"], - required: true - }, - type: "number", - }, - }, - required: ["age"] - } -}]; -const SAMPLE_CONFIG: IImperativeConfig = { - definitions: [ - { - name: "profile", - type: "command", - options: [], - profile: { - required: ["banana"] - }, - description: "my command", - handler: __dirname + "/handler/SampleHandler" - } - ], - productDisplayName: "My product (packagejson)", - defaultHome: T.TEST_HOME, - rootCommandDescription: "My Product CLI", - profiles: PROFILE_CONFIGURATIONS -}; - -describe("Imperative should allow CLI implementations to configure their own profiles and types", function () { - - /** - * Clean up the home directory before and after each test. - */ - beforeAll(function () { - T.rimraf(T.TEST_HOME); - // return Imperative.init(SAMPLE_CONFIG).then(() => { - // Imperative.api.profileManager("banana").createProfile({name: "legit", age: BANANA_AGE}, - // true, true, - // (error: Error, filePath: string, overwritten: boolean) => { - // expect(error, "Should not get error for valid profile:" + T.inspect(error)).to.not.exist; - // }); - // }); - }); - afterAll(function () { - T.rimraf(T.TEST_HOME); - }); - - function issueCommand(optionString: string, shouldSucceed: boolean, expectedText?: string[]) { - const options = yargs.parse(optionString); - // options._ = ["test", "validation-test"].concat(options._); // fake out command structure - options[Constants.JSON_OPTION] = true; - const fakeParent: ICommandDefinition = { - name: undefined, - description: "", type: "group", - children: [SAMPLE_CONFIG.definitions[0]] - }; - const helpGenerator: AbstractHelpGenerator = new DefaultHelpGenerator({ - primaryHighlightColor: "yellow", - produceMarkdown: false, - rootCommandName: "dummy" - }, { - fullCommandTree: fakeParent, - commandDefinition: SAMPLE_CONFIG.definitions[0] - }); - const cmdProcessorParms: ICommandProcessorParms = { - definition: SAMPLE_CONFIG?.definitions?.[0] as ICommandDefinition, - helpGenerator: helpGenerator, - profileManagerFactory: new BasicProfileManagerFactory(T.createUniqueTestDataDir(), PROFILE_CONFIGURATIONS), - rootCommandName: "zoweCmdName", - commandLine: "/path/to/zoweCmdName", - envVariablePrefix: "ZOWE_CLI", - fullDefinition: fakeParent, - promptPhrase: "Any prompt will do:" - }; - return new CommandProcessor(cmdProcessorParms).invoke({arguments: options, responseFormat: "json"}).then( - (completedResponse: ICommandResponse) => { - logger.debug(JSON.stringify(completedResponse)); - if (shouldSucceed) { - // Command should have succeeded - expect(completedResponse.success).toEqual(true); - } else { - // "Command should have failed" - expect(completedResponse.success).toEqual(false); - } - if (!(expectedText == null) && expectedText.length > 0) { - const fullText = completedResponse.stdout.toString() + - completedResponse.stderr.toString(); - for (const text of expectedText) { - expect(fullText).toContain(text); - } - } - // done(); - }); - } - - // eslint-disable-next-line jest/expect-expect, jest/no-disabled-tests - it.skip("We should be able to issue a command and have a profile be automatically loaded", function () { - // return issueCommand.bind(this, ["profile"], true)(); - }); -}); diff --git a/packages/imperative/__tests__/src/packages/profiles/__integration__/__snapshots__/BasicProfileManager.initialize.integration.test.ts.snap b/packages/imperative/__tests__/src/packages/profiles/__integration__/__snapshots__/BasicProfileManager.initialize.integration.test.ts.snap deleted file mode 100644 index a1175cb2c3..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/__integration__/__snapshots__/BasicProfileManager.initialize.integration.test.ts.snap +++ /dev/null @@ -1,72 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Basic Profile Manager Initialize Should allow us to initialize the environment and create a profile manager 1`] = ` -"defaultProfile: null -configuration: - type: banana - schema: - type: object - title: 'The Banana command profile schema' - description: 'The Banana command profile schema' - properties: - age: - optionDefinition: - description: 'The age of the Banana' - type: number - name: age - aliases: - - a - required: true - type: number - required: - - age -" -`; - -exports[`Basic Profile Manager Initialize Should allow us to initialize the environment and create a profile manager 2`] = ` -"defaultProfile: null -configuration: - type: secure_orange - schema: - type: object - title: 'The secure_orange command profile schema' - description: 'The secure_orange command profile schema' - properties: - username: - optionDefinition: - description: 'The username of the secure_orange' - type: string - name: username - type: string - password: - optionDefinition: - description: 'The password of the secure_orange' - type: string - name: password - type: string - required: [] -" -`; - -exports[`Basic Profile Manager Initialize Should allow us to initialize the environment and create a profile manager 3`] = ` -"defaultProfile: null -configuration: - type: strawberry - schema: - type: object - title: 'The strawberry command profile schema' - description: 'The strawberry command profile schema' - properties: - age: - optionDefinition: - description: 'The age of the strawberry' - type: number - name: age - aliases: - - a - required: true - type: number - required: - - age -" -`; diff --git a/packages/imperative/__tests__/src/packages/profiles/__integration__/__snapshots__/BasicProfileManager.integration.test.ts.snap b/packages/imperative/__tests__/src/packages/profiles/__integration__/__snapshots__/BasicProfileManager.integration.test.ts.snap deleted file mode 100644 index b2866c92d9..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/__integration__/__snapshots__/BasicProfileManager.integration.test.ts.snap +++ /dev/null @@ -1,13 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Imperative should allow CLI implementations to configure their own profiles and types should be able to create a basic profile and load as the default 1`] = ` -Object { - "age": 1000, -} -`; - -exports[`Imperative should allow CLI implementations to configure their own profiles and types should be able to create a basic profile and load that profile 1`] = ` -Object { - "age": 1000, -} -`; diff --git a/packages/imperative/__tests__/src/packages/profiles/src/constants/BasicProfileManagerTestConstants.ts b/packages/imperative/__tests__/src/packages/profiles/src/constants/BasicProfileManagerTestConstants.ts deleted file mode 100644 index ba71a6207c..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/src/constants/BasicProfileManagerTestConstants.ts +++ /dev/null @@ -1,124 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IImperativeConfig } from "../../../../../../src/index"; -import * as TestUtils from "../../../../TestUtil"; -import { ICommandProfileTypeConfiguration } from "../../../../../../src/cmd"; - -/** - * Get a config and set the home directory. - * @export - * @param {string} home - * @returns - */ -export function getConfig(home: string) { - const copy = JSON.parse(JSON.stringify(SAMPLE_IMPERATIVE_CONFIG_WITH_PROFILES)); - copy.defaultHome = home; - return copy; -} - -export const PROFILE_TYPE = { - BANANA: "banana", - SECURE_ORANGE: "secure_orange", - STRAWBERRY: "strawberry" -}; - -const bananaProfile: ICommandProfileTypeConfiguration = { - type: PROFILE_TYPE.BANANA, - schema: { - type: "object", - title: "The Banana command profile schema", - description: "The Banana command profile schema", - properties: { - age: { - optionDefinition: { - description: "The age of the Banana", - type: "number", - name: "age", aliases: ["a"], - required: true - }, - type: "number", - }, - }, - required: ["age"] - } -}; - -const secureOrangeProfile: ICommandProfileTypeConfiguration = { - type: PROFILE_TYPE.SECURE_ORANGE, - schema: { - type: "object", - title: "The secure_orange command profile schema", - description: "The secure_orange command profile schema", - properties: { - username: { - optionDefinition: { - description: "The username of the secure_orange", - type: "string", - name: "username", - }, - type: "string", - }, - password: { - optionDefinition: { - description: "The password of the secure_orange", - type: "string", - name: "password", - }, - type: "string", - }, - }, - required: [] - } -}; - -const strawberryProfile: ICommandProfileTypeConfiguration = { - type: PROFILE_TYPE.STRAWBERRY, - schema: { - type: "object", - title: "The strawberry command profile schema", - description: "The strawberry command profile schema", - properties: { - age: { - optionDefinition: { - description: "The age of the strawberry", - type: "number", - name: "age", aliases: ["a"], - required: true - }, - type: "number", - }, - }, - required: ["age"] - } -}; - -export const PROFILE_TYPE_CONFIGURATION: ICommandProfileTypeConfiguration[] = [ - bananaProfile, - secureOrangeProfile, - strawberryProfile -]; - -export const BANANA_AGE: number = 1000; -export const SAMPLE_IMPERATIVE_CONFIG_WITH_PROFILES: IImperativeConfig = { - definitions: [ - { - name: "hello", - type: "command", - options: [], - description: "my command" - } - ], - productDisplayName: "My product (packagejson)", - defaultHome: TestUtils.TEST_HOME, - rootCommandDescription: "My Product CLI", - profiles: PROFILE_TYPE_CONFIGURATION -}; diff --git a/packages/imperative/__tests__/src/packages/profiles/src/constants/ProfileInfoConstants.ts b/packages/imperative/__tests__/src/packages/profiles/src/constants/ProfileInfoConstants.ts deleted file mode 100644 index f373ba005e..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/src/constants/ProfileInfoConstants.ts +++ /dev/null @@ -1,255 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IImperativeConfig, IConfigLogging, IConfig, IConfigSchema } from "../../../../../../src"; - -export const Log4jsConfig: IConfigLogging = { - "log4jsConfig": { - "appenders": { - "default": { - "type": "fileSync", - "layout": { - "type": "pattern", - "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m" - }, - "filename": "logs/imperative.log" - }, - "imperative": { - "type": "fileSync", - "layout": { - "type": "pattern", - "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m" - }, - "filename": "logs/imperative.log" - }, - "app": { - "type": "fileSync", - "layout": { - "type": "pattern", - "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m" - }, - "filename": "logs/test_app.log" - } - }, - "categories": { - "default": { - "appenders": ["default"], - "level": "DEBUG" - }, - "imperative": { - "appenders": ["imperative"], - "level": "DEBUG" - }, - "app": { - "appenders": ["app"], - "level": "DEBUG" - } - } - } -}; - -export const TestAppImperativeConfig: IImperativeConfig = { - profiles: [{ - type: "test_app", - schema: { - type: "object", - title: "test_app Profile", - description: "test_app profile for testing purposes", - properties: { - plain: { - type: "string", - optionDefinition: { - name: "plain", - description: "plain text property", - type: "string", - } - }, - secure: { - type: "string", - secure: true, - optionDefinition: { - name: "secure", - description: "secure property", - type: "string", - } - }, - nested: { - type: "object", - optionDefinitions: [ - { - name: "nested-plain", - description: "plain text property", - type: "string", - }, - { - // TODO: Nested secure properties not able to be defined in the schema? - // secure: true, - name: "nested-secure", - description: "secure property", - type: "string", - }, - ] - }, - }, - required: [] - } - }] -}; - -export const test_appConfigJson: IConfig = { - "$schema": "./test_app.schema.json", - "profiles": { - "test_app": { - "type": "test_app", - "properties": { - "plain": "test", - "secure": "secret", - "nested": { - "nested-plain": " nested-test", - "nested-secure": "nested-secret" - } - }, - "secure": [ - "secure", - "nested.nested-secure" - ] - } - }, - "defaults": { - "test_app": "test_app" - }, - "autoStore": true -}; - -export const test_appSchemaJson: IConfigSchema = { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$version": "1.0", - "type": "object", - "description": "Zowe configuration", - "properties": { - "profiles": { - "type": "object", - "description": "Mapping of profile names to profile configurations", - "patternProperties": { - "^\\S*$": { - "type": "object", - "description": "Profile configuration object", - "properties": { - "type": { - "description": "Profile type", - "type": "string", - "enum": [ - "test_app" - ] - }, - "properties": { - "description": "Profile properties object", - "type": "object" - }, - "profiles": { - "description": "Optional subprofile configurations", - "type": "object", - "$ref": "#/properties/profiles" - }, - "secure": { - "description": "Secure property names", - "type": "array", - "items": { - "type": "string" - }, - "uniqueItems": true - } - }, - "allOf": [ - { - "if": { - "properties": { - "type": false - } - }, - "then": { - "properties": { - "properties": { - "title": "Missing profile type" - } - } - } - }, - { - "if": { - "properties": { - "type": { - "const": "test_app" - } - } - }, - "then": { - "properties": { - "properties": { - "type": "object", - "title": "test_app Profile", - "description": "test_app Profile", - "properties": { - "plain": { - "type": "string", - "description": "plain text property" - }, - "secure": { - "type": "string", - "description": "secure property" - }, - "nested": { - "type": "object", - "properties": { - "nested-plain": { - "type": "string", - "description": "nested plain text property" - }, - "nested-secure": { - "type": "string", - "description": "nested secure property" - } - } - } - }, - "required": [] - }, - "secure": { - "items": { - "enum": [ - "secure", - "nested.nested-secure" - ] - } - } - } - } - } - ] - } - } - }, - "defaults": { - "type": "object", - "description": "Mapping of profile types to default profile names", - "properties": { - "test_app": { - "description": "Default test_app profile", - "type": "string" - } - } - }, - "autoStore": { - "type": "boolean", - "description": "If true, values you enter when prompted are stored for future use" - } - } -}; diff --git a/packages/imperative/__tests__/src/packages/profiles/src/handler/SampleHandler.ts b/packages/imperative/__tests__/src/packages/profiles/src/handler/SampleHandler.ts deleted file mode 100644 index 6f5235a569..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/src/handler/SampleHandler.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandHandler, IHandlerParameters } from "../../../../../../src/cmd"; -import { ImperativeError } from "../../../../../../src/error"; - -export default class SampleHandler implements ICommandHandler { - public async process(commandParameters: IHandlerParameters) { - // eslint-disable-next-line deprecation/deprecation - const profile: any = commandParameters.profiles.get("banana"); - if (profile == null) { - const errMsg = commandParameters.response.console.error("Failed to load a profile of type banana"); - throw new ImperativeError({msg: errMsg}); - } - } -} diff --git a/packages/imperative/__tests__/src/packages/profiles/test_app/TestApp.ts b/packages/imperative/__tests__/src/packages/profiles/test_app/TestApp.ts deleted file mode 100644 index 549f9a06dd..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/test_app/TestApp.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { TestProfileLoader } from "./TestProfileLoader"; -import { TestAppImperativeConfig } from "../src/constants/ProfileInfoConstants"; -import { CliProfileManager } from "../../../../../src/cmd/src/profiles/CliProfileManager"; -import { Logger } from "../../../../../src/logger/src/Logger"; -import * as path from "path"; - -const setupOldProfiles = async (projectDir: string) => { - await CliProfileManager.initialize({ - configuration: TestAppImperativeConfig.profiles, - profileRootDirectory: path.join(projectDir, "profiles"), - }); -}; - -const log = (logger: Logger, msg: string, ...args: any) => { - const loggerFunctions: string[] = ["trace", "debug", "simple", "info", "warn", "error", "fatal"]; - for (const fName of loggerFunctions) { - (logger[fName as keyof Logger] as any)(msg, ...args); - } -}; - -/** - * Test application for integration test purposes. - * This test application focuses on the ProfileInfo API usage. - * node --require "ts-node/register" /__tests__/src/packages/profiles/test_app/TestApp.ts - * node --require "ts-node/register" /root/gh/zowe/imperative/__tests__/src/packages/profiles/test_app/TestApp.ts /root/gh/test/del/del2 - */ -(async (args: string[]) => { - const projectDir = args[2]; - - // Just in case we want to write integration tests for ProfileInfo APIs for OLD profiles - await setupOldProfiles(projectDir); - - const loader = new TestProfileLoader(projectDir); - - const profile = await loader.defaultProfile(); - log(loader.appLogger, "default profile:", profile); - log(loader.impLogger, "default profile:", profile); - - const mergedArgs = loader.getProperties(profile); - log(loader.appLogger, "merged args:", mergedArgs); - log(loader.impLogger, "merged args:", mergedArgs); - - // eslint-disable-next-line no-console - console.log("Done!\nPlease check the logs at:", projectDir + "/logs"); -})(process.argv); diff --git a/packages/imperative/__tests__/src/packages/profiles/test_app/TestProfileLoader.ts b/packages/imperative/__tests__/src/packages/profiles/test_app/TestProfileLoader.ts deleted file mode 100644 index 1bdeb64cc7..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/test_app/TestProfileLoader.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { Logger } from "../../../../../src/logger/src/Logger"; -import { ProfileInfo } from "../../../../../src/config/src/ProfileInfo"; -import { Log4jsConfig } from "../src/constants/ProfileInfoConstants"; -import { IProfAttrs } from "../../../../../src"; -import * as path from "path"; - -export class TestProfileLoader { - private mProfileInfo: ProfileInfo; - - public appLogger: Logger; - public impLogger: Logger; - public projectDir: string = null; - public appName = "test_app"; - constructor(projectDir: string) { - this.projectDir = projectDir; - this.initLogger(); - this.appLogger = Logger.getAppLogger(); - this.impLogger = Logger.getImperativeLogger(); - this.mProfileInfo = new ProfileInfo(this.appName); - } - - public initLogger() { - const loggerConfig = Log4jsConfig; - for (const appenderName in loggerConfig.log4jsConfig.appenders) { - loggerConfig.log4jsConfig.appenders[appenderName].filename = path.join( - this.projectDir, Log4jsConfig.log4jsConfig.appenders[appenderName].filename); - } - Logger.initLogger(loggerConfig); - } - - public async defaultProfile() { - await this.mProfileInfo.readProfilesFromDisk({ projectDir: this.projectDir }); - const profile = this.mProfileInfo.getDefaultProfile(this.appName); - return profile; - } - - public getProperties(profile: IProfAttrs) { - return this.mProfileInfo.mergeArgsForProfile(profile, { getSecureVals: true }); - } -} \ No newline at end of file diff --git a/packages/imperative/__tests__/src/packages/profiles/test_cli/TestCLI.ts b/packages/imperative/__tests__/src/packages/profiles/test_cli/TestCLI.ts deleted file mode 100644 index 9b92411e1c..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/test_cli/TestCLI.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { Imperative } from "../../../../../src/imperative"; - - -process.on("unhandledRejection", (err) => { - process.stderr.write("Err: " + err + "\n"); -}); - -Imperative.init({configurationModule: __dirname + "/TestConfiguration.ts"}).then(() => Imperative.parse()); -// Imperative.parse(); diff --git a/packages/imperative/__tests__/src/packages/profiles/test_cli/TestConfiguration.ts b/packages/imperative/__tests__/src/packages/profiles/test_cli/TestConfiguration.ts deleted file mode 100644 index c2fc87d90a..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/test_cli/TestConfiguration.ts +++ /dev/null @@ -1,116 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IImperativeConfig } from "../../../../../src/imperative"; -import * as path from "path"; - -const config: IImperativeConfig = { - definitions: [ - { - name: "display-profile", - description: "Display profile content", - type: "command", - profile: { - required: ["username-password"] - }, - handler: path.join(__dirname, "handlers", "DisplayProfileHandler.ts") - }, - { - name: "display-non-keytar", - description: "Display handler without require keytar", - type: "command", - handler: path.join(__dirname, "handlers", "NonKeytarHandler.ts") - } - ], - rootCommandDescription: "Sample command line interface", - defaultHome: path.join(__dirname, "../../../../__results__/.packages-profiles"), - productDisplayName: "Test CLI with Profiles", - name: "example_with_profiles", - profiles: [ - { - type: "username-password", - schema: { - type: "object", - title: "Profile Manager Test Profile", - description: "user name and password test profile", - properties: { - username: { - optionDefinition: { - description: "User Name", - type: "string", - name: "username", - required: true - }, - secure: true, - type: "string" - }, - password: { - optionDefinition: { - description: "Password", - type: "number", - name: "password", - required: true - }, - secure: true, - type: "number" - }, - account: { - optionDefinition: { - description: "Account", - type: "string", - name: "account", - required: true - }, - secure: true, - type: "string" - }, - myParent: { - type: "object", - properties: { - securedProperty: { - type: "object", - properties: { - mySecuredChild: { - optionDefinition: { - description: "The secured property", - type: "string", - name: "sec1", - required: true - }, - secure: true, - type: "string" - } - } - }, - insecuredProperty: { - type: "object", - properties: { - myInSecuredChild: { - optionDefinition: { - description: "The insecured property", - type: "string", - name: "insec1", - required: true - }, - secure: false, - type: "string" - } - } - } - } - } - } - } - } - ] -}; - -export = config; diff --git a/packages/imperative/__tests__/src/packages/profiles/test_cli/TestCustomCredClass.ts b/packages/imperative/__tests__/src/packages/profiles/test_cli/TestCustomCredClass.ts deleted file mode 100644 index 5d50a556f2..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/test_cli/TestCustomCredClass.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { Imperative } from "../../../../../src/imperative"; -import * as path from "path"; - - -process.on("unhandledRejection", (err) => { - process.stderr.write("Err: " + err + "\n"); -}); - -Imperative.init({configurationModule: path.join(__dirname, "/TestCustomCredClassConfiguration.ts")}).then(() => Imperative.parse()); - diff --git a/packages/imperative/__tests__/src/packages/profiles/test_cli/TestCustomCredClassConfiguration.ts b/packages/imperative/__tests__/src/packages/profiles/test_cli/TestCustomCredClassConfiguration.ts deleted file mode 100644 index 3ace8b9094..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/test_cli/TestCustomCredClassConfiguration.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IImperativeConfig } from "../../../../../src/imperative"; -import { CustomCredentialManagerClass } from "./customCredential/CustomCredentialManagerClass"; -import * as path from "path"; - -const config: IImperativeConfig = { - definitions: [ - { - name: "display-profile", - description: "Display profile content", - type: "command", - profile: { - required: ["username-password"] - }, - handler: path.join(__dirname, "handlers", "DisplayProfileHandler.ts") - } - ], - rootCommandDescription: "Sample command line interface", - defaultHome: path.join(__dirname, "../../../../__results__/.packages-profiles"), - productDisplayName: "Test CLI with Profiles", - name: "example_with_profiles", - profiles: [ - { - type: "username-password", - schema: { - type: "object", - title: "Profile Manager Test Profile", - description: "user name and password test profile", - properties: { - username: { - optionDefinition: { - description: "Username", - type: "string", - name: "username", - required: true - }, - secure: true, - type: "string" - }, - password: { - optionDefinition: { - description: "Password", - type: "string", - name: "password", - required: true - }, - secure: true, - type: "string" - } - }, - }, - }], - overrides: { - CredentialManager: CustomCredentialManagerClass - } -}; - -export = config; diff --git a/packages/imperative/__tests__/src/packages/profiles/test_cli/TestCustomCredString.ts b/packages/imperative/__tests__/src/packages/profiles/test_cli/TestCustomCredString.ts deleted file mode 100644 index ffa9a3293a..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/test_cli/TestCustomCredString.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { Imperative } from "../../../../../src/imperative"; -import * as path from "path"; - - -process.on("unhandledRejection", (err) => { - process.stderr.write("Err: " + err + "\n"); -}); - -Imperative.init({configurationModule: path.join(__dirname, "/TestCustomCredStringConfiguration.ts")}).then(() => Imperative.parse()); - diff --git a/packages/imperative/__tests__/src/packages/profiles/test_cli/TestCustomCredStringConfiguration.ts b/packages/imperative/__tests__/src/packages/profiles/test_cli/TestCustomCredStringConfiguration.ts deleted file mode 100644 index a6b26796bd..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/test_cli/TestCustomCredStringConfiguration.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IImperativeConfig } from "../../../../../src/imperative"; -import * as path from "path"; - -const config: IImperativeConfig = { - definitions: [ - { - name: "display-profile", - description: "Display profile content", - type: "command", - profile: { - required: ["username-password"] - }, - handler: path.join(__dirname, "handlers", "DisplayProfileHandler.ts") - } - ], - rootCommandDescription: "Sample command line interface", - defaultHome: path.join(__dirname, "../../../../__results__/.packages-profiles"), - productDisplayName: "Test CLI with Profiles", - name: "example_with_profiles", - profiles: [ - { - type: "username-password", - schema: { - type: "object", - title: "Profile Manager Test Profile", - description: "user name and password test profile", - properties: { - username: { - optionDefinition: { - description: "Username", - type: "string", - name: "username", - required: true - }, - secure: true, - type: "string" - }, - password: { - optionDefinition: { - description: "Password", - type: "string", - name: "password", - required: true - }, - secure: true, - type: "string" - } - }, - }, - }], - overrides: { - CredentialManager: "./customCredential/CustomCredentialManager.ts" - } -}; - -export = config; diff --git a/packages/imperative/__tests__/src/packages/profiles/test_cli/customCredential/CustomCredentialManager.ts b/packages/imperative/__tests__/src/packages/profiles/test_cli/customCredential/CustomCredentialManager.ts deleted file mode 100644 index cacdef01b3..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/test_cli/customCredential/CustomCredentialManager.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { AbstractCredentialManager, SecureCredential } from "../../../../../../src/security"; - -export = class CustomCredentialManager extends AbstractCredentialManager { - constructor() { - super("DummyService", "DummyName"); - } - - public async loadCredentials(account: string): Promise { - // We need to stringify to simulate the stored value that we are loading - const cred: SecureCredential = Buffer.from(JSON.stringify("custom")).toString("base64"); - return cred; - } - - public async saveCredentials(account: string, credentials: SecureCredential): Promise { - return; - } - - public async deleteCredentials(account: string): Promise { - return; - } -}; diff --git a/packages/imperative/__tests__/src/packages/profiles/test_cli/customCredential/CustomCredentialManagerClass.ts b/packages/imperative/__tests__/src/packages/profiles/test_cli/customCredential/CustomCredentialManagerClass.ts deleted file mode 100644 index c53c1adc8c..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/test_cli/customCredential/CustomCredentialManagerClass.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { AbstractCredentialManager, SecureCredential } from "../../../../../../src/security"; - -export class CustomCredentialManagerClass extends AbstractCredentialManager { - constructor() { - super("DummyService", "DummyName"); - } - - public async loadCredentials(account: string): Promise { - // We need to stringify to simulate the stored value that we are loading - const cred: SecureCredential = Buffer.from(JSON.stringify("custom")).toString("base64"); - return cred; - } - - public async saveCredentials(account: string, credentials: SecureCredential): Promise { - return; - } - - public async deleteCredentials(account: string): Promise { - return; - } -} diff --git a/packages/imperative/__tests__/src/packages/profiles/test_cli/handlers/DisplayProfileHandler.ts b/packages/imperative/__tests__/src/packages/profiles/test_cli/handlers/DisplayProfileHandler.ts deleted file mode 100644 index 0f9ab9fce6..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/test_cli/handlers/DisplayProfileHandler.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandHandler, IHandlerParameters } from "../../../../../../src/cmd"; - -export default class DisplayProfileHandler implements ICommandHandler { - public async process(params: IHandlerParameters): Promise { - // eslint-disable-next-line deprecation/deprecation - const profile = params.profiles.get("username-password"); - params.response.console.log(JSON.stringify(profile)); - } -} diff --git a/packages/imperative/__tests__/src/packages/profiles/test_cli/handlers/NonKeytarHandler.ts b/packages/imperative/__tests__/src/packages/profiles/test_cli/handlers/NonKeytarHandler.ts deleted file mode 100644 index 2871ebe061..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/test_cli/handlers/NonKeytarHandler.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandHandler, IHandlerParameters } from "../../../../../../src/cmd"; - -export default class NoneKeytarHandler implements ICommandHandler { - public async process(params: IHandlerParameters): Promise { - params.response.console.log("This handler does not require keytar"); - } -} diff --git a/packages/imperative/__tests__/src/packages/profiles/test_cli/package.json b/packages/imperative/__tests__/src/packages/profiles/test_cli/package.json deleted file mode 100644 index 3e5cc07e11..0000000000 --- a/packages/imperative/__tests__/src/packages/profiles/test_cli/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "test-cli-for-profiles", - "dependencies": { - "@zowe/secrets-for-zowe-sdk": "plaintext" - } -} \ No newline at end of file diff --git a/packages/imperative/__tests__/tsconfig.json b/packages/imperative/__tests__/tsconfig.json index e15ba062f9..df9be0345c 100644 --- a/packages/imperative/__tests__/tsconfig.json +++ b/packages/imperative/__tests__/tsconfig.json @@ -1,35 +1,27 @@ { - // tsconfig for test files // - "compilerOptions": { - "types": ["node", "jest"], - "lib": ["esnext"], - "target": "es2015", - "module": "commonjs", - "declaration": true, - "moduleResolution": "node", - "noImplicitAny": true, - "preserveConstEnums": true, - "experimentalDecorators": true, - "removeComments": false, - "pretty": true, - "sourceMap": true, - "newLine": "lf", - "esModuleInterop": true - }, - "include": [ - "**/*.test.ts", - "**/*.subtest.ts", - "**/__tests__/**/*", - "../**/*.test.ts", - "../**/*.subtest.ts", - "../**/__tests__/**/*" - ], - "exclude": [ - "lib", - "node_modules" - ], - "files": [ - "../../__types__/wontache.d.ts" - ], - "allowJs": true -} \ No newline at end of file + // tsconfig for test files // + "compilerOptions": { + "types": ["node", "jest"], + "lib": ["esnext"], + "target": "es2015", + "module": "commonjs", + "declaration": true, + "moduleResolution": "node", + "noImplicitAny": true, + "preserveConstEnums": true, + "experimentalDecorators": true, + "removeComments": false, + "pretty": true, + "sourceMap": true, + "newLine": "lf", + "esModuleInterop": true + }, + "include": [ + "**/*.test.ts", + "**/__tests__/**/*" + ], + "exclude": [ + "lib", + "node_modules" + ] +} diff --git a/packages/imperative/package.json b/packages/imperative/package.json index c2cf1b4dfd..211b48a991 100644 --- a/packages/imperative/package.json +++ b/packages/imperative/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/imperative", - "version": "5.27.1", + "version": "8.0.0-next.202409111528", "description": "framework for building configurable CLIs", "author": "Zowe", "license": "EPL-2.0", @@ -45,74 +45,68 @@ "prepublishOnly": "cd web-help && npm run deps:lockfile" }, "dependencies": { - "@types/yargs": "13.0.4", - "chalk": "2.4.2", - "cli-table3": "0.6.2", - "comment-json": "4.1.1", - "cross-spawn": "7.0.3", - "dataobject-parser": "1.2.25", - "deepmerge": "4.2.2", - "diff": "5.1.0", + "@types/yargs": "^17.0.32", + "chalk": "^4.1.2", + "cli-table3": "^0.6.3", + "comment-json": "~4.2.3", + "cross-spawn": "^7.0.3", + "dataobject-parser": "^1.2.25", + "deepmerge": "^4.3.1", + "diff": "^5.2.0", "diff2html": "3.4.20-usewontache.1.60e7a2e", - "fast-glob": "3.2.7", - "fastest-levenshtein": "1.0.12", - "find-up": "4.1.0", - "fs-extra": "9.1.0", + "fast-glob": "^3.3.2", + "fastest-levenshtein": "^1.0.16", + "find-up": "^5.0.0", + "fs-extra": "^11.0.0", "http-proxy-agent": "7.0.2", "https-proxy-agent": "7.0.4", - "jest-diff": "27.0.6", - "js-yaml": "4.1.0", - "jsonfile": "6.1.0", - "jsonschema": "1.4.1", - "lodash": "4.17.21", - "lodash-deep": "2.0.0", - "log4js": "6.4.6", - "markdown-it": "14.1.0", - "mustache": "4.2.0", - "npm-package-arg": "9.1.0", - "opener": "1.5.2", - "pacote": "17.0.6", - "prettyjson": "1.2.2", - "progress": "2.0.3", - "read": "1.0.7", - "readline-sync": "1.4.10", - "semver": "7.5.4", - "stack-trace": "0.0.10", - "strip-ansi": "6.0.1", - "which": "4.0.0", - "wrap-ansi": "7.0.0", - "yamljs": "0.3.0", - "yargs": "15.3.1" + "jest-diff": "^29.0.0", + "js-yaml": "^4.1.0", + "jsonfile": "^6.0.0", + "jsonschema": "^1.4.1", + "lodash": "^4.17.21", + "lodash-deep": "^2.0.0", + "log4js": "^6.9.1", + "markdown-it": "^14.1.0", + "mustache": "^4.2.0", + "npm-package-arg": "^11.0.1", + "opener": "^1.5.2", + "pacote": "^18.0.6", + "prettyjson": "^1.2.5", + "progress": "^2.0.3", + "read": "^3.0.1", + "semver": "^7.5.2", + "stack-trace": "^0.0.10", + "strip-ansi": "^6.0.1", + "which": "^4.0.0", + "wrap-ansi": "^7.0.0", + "yargs": "^17.7.2" }, "devDependencies": { - "@types/cross-spawn": "^6.0.2", - "@types/diff": "^5.0.2", - "@types/find-up": "^2.1.1", - "@types/fs-extra": "^9.0.13", - "@types/glob": "^7.1.1", - "@types/jsonfile": "^6.1.0", - "@types/lodash": "^4.14.165", - "@types/lodash-deep": "^2.0.0", - "@types/mustache": "^0.8.32", - "@types/npm-package-arg": "^6.1.0", - "@types/pacote": "^11.1.0", - "@types/progress": "^2.0.3", - "@types/readline-sync": "^1.4.3", - "@types/rimraf": "^3.0.2", - "@types/stack-trace": "^0.0.29", - "@zowe/secrets-for-zowe-sdk": "^7.18.0", - "concurrently": "^7.5.0", - "cowsay": "^1.2.1", - "deep-diff": "^0.3.8", + "@types/cross-spawn": "^6.0.6", + "@types/diff": "^5.0.9", + "@types/fs-extra": "^11.0.4", + "@types/glob": "^8.1.0", + "@types/jsonfile": "^6.1.4", + "@types/lodash": "^4.17.6", + "@types/lodash-deep": "^2.0.4", + "@types/mustache": "^4.2.5", + "@types/npm-package-arg": "^6.1.4", + "@types/pacote": "^11.1.8", + "@types/progress": "^2.0.7", + "@types/stack-trace": "^0.0.33", + "@zowe/secrets-for-zowe-sdk": "8.0.0-next.202409111528", + "concurrently": "^8.0.0", + "cowsay": "^1.6.0", + "deep-diff": "^1.0.0", "get-function-arguments": "^1.0.0", "http-server": "^14.1.1", "stream-to-string": "^1.2.0", - "tsc-watch": "^5.0.3", - "uuid": "^3.3.2", + "uuid": "^10.0.0", "web-help": "file:web-help", - "yargs-parser": "^18.1.2" + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.12.0" } } diff --git a/packages/imperative/src/cmd/__tests__/CommandProcessor.unit.test.ts b/packages/imperative/src/cmd/__tests__/CommandProcessor.unit.test.ts index 2ea8e55955..b48f3c2d23 100644 --- a/packages/imperative/src/cmd/__tests__/CommandProcessor.unit.test.ts +++ b/packages/imperative/src/cmd/__tests__/CommandProcessor.unit.test.ts @@ -15,19 +15,17 @@ import { CommandProcessor } from "../src/CommandProcessor"; import { ICommandResponse } from "../src/doc/response/response/ICommandResponse"; import { CommandResponse } from "../src/response/CommandResponse"; import { IHelpGenerator } from "../src/help/doc/IHelpGenerator"; -import { BasicProfileManager, IProfileManagerFactory, IProfileTypeConfiguration } from "../../profiles"; import { ImperativeError } from "../../error"; import { ICommandValidatorResponse } from "../src/doc/response/response/ICommandValidatorResponse"; import { SharedOptions } from "../src/utils/SharedOptions"; -import { CommandProfileLoader } from "../src/profiles/CommandProfileLoader"; import { CliUtils } from "../../utilities/src/CliUtils"; import { WebHelpManager } from "../src/help/WebHelpManager"; import { ImperativeConfig } from "../../utilities/src/ImperativeConfig"; import { setupConfigToLoad } from "../../../__tests__/src/TestUtil"; -import { EnvFileUtils, NextVerFeatures } from "../../utilities"; +import { EnvFileUtils } from "../../utilities"; import { join } from "path"; import { Config } from "../../config"; -import { LoggerUtils } from "../.."; +import { LoggerUtils } from "../../logger/src/LoggerUtils"; jest.mock("../src/syntax/SyntaxValidator"); jest.mock("../src/utils/SharedOptions"); @@ -184,59 +182,6 @@ const SAMPLE_COMMAND_REAL_HANDLER_WITH_DEFAULT_OPT: ICommandDefinition = { } }; -// A fake instance of the profile manager factory -const FAKE_PROFILE_MANAGER_FACTORY: IProfileManagerFactory = { - getManager: () => { - return new BasicProfileManager({ - profileRootDirectory: "FAKE_ROOT", - type: "banana", - typeConfigurations: [ - { - type: "banana", - schema: { - title: "fake banana schema", - type: "object", - description: "", - properties: {} - } - } - ] - }); - } -}; - -// A fake instance of the profile manager factory with props -const FAKE_PROFILE_MANAGER_FACTORY_WITH_PROPS: IProfileManagerFactory = { - getManager: () => { - return new BasicProfileManager({ - profileRootDirectory: "FAKE_ROOT", - type: "banana", - typeConfigurations: [ - { - type: "banana", - schema: { - title: "fake banana schema", - type: "object", - description: "", - properties: { - color: { - type: "string", - optionDefinition: { - name: "color", - aliases: ["c"], - description: "The color of the banana.", - type: "string", - required: true, - }, - } - } - } - } - ] - }); - } -}; - // A fake instance of the help generator const FAKE_HELP_GENERATOR: IHelpGenerator = { buildHelp: function buildHelp(): string { @@ -247,6 +192,11 @@ const FAKE_HELP_GENERATOR: IHelpGenerator = { const ENV_VAR_PREFIX: string = "UNIT_TEST"; describe("Command Processor", () => { + beforeEach(() => { + // Mock read stdin + jest.spyOn(SharedOptions, "readStdinIfRequested").mockResolvedValueOnce(false); + }); + // Restore everything after each test afterEach(() => { process.stdout.write = ORIGINAL_STDOUT_WRITE; @@ -262,7 +212,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -293,7 +242,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: undefined, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -313,27 +261,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: undefined, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, - rootCommandName: SAMPLE_ROOT_COMMAND, - commandLine: "", - promptPhrase: "dummydummy" - }); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect no profile manager factory supplied", () => { - let error; - try { - const processor: CommandProcessor = new CommandProcessor({ - envVariablePrefix: ENV_VAR_PREFIX, - definition: SAMPLE_COMMAND_DEFINITION, - helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: undefined, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -353,7 +280,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: undefined, commandLine: "", promptPhrase: "dummydummy" @@ -373,7 +299,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: "", commandLine: "", promptPhrase: "dummydummy" @@ -393,7 +318,6 @@ describe("Command Processor", () => { envVariablePrefix: undefined, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -411,7 +335,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -424,7 +347,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -437,7 +359,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -450,7 +371,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -463,7 +383,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -476,12 +395,14 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" }); - expect(processor.profileFactory).toEqual(FAKE_PROFILE_MANAGER_FACTORY); + expect(processor instanceof CommandProcessor).toBe(true); + expect(processor.envVariablePrefix).toEqual(ENV_VAR_PREFIX); + expect(processor.definition).toEqual(SAMPLE_COMMAND_DEFINITION); + expect(processor.promptPhrase).toEqual("dummydummy"); }); it("should build the help if requested", () => { @@ -493,7 +414,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -518,7 +438,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -544,7 +463,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -570,7 +488,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -592,7 +509,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -612,7 +528,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -635,7 +550,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -662,7 +576,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -685,7 +598,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -708,7 +620,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -732,7 +643,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -756,7 +666,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -780,7 +689,6 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -807,7 +715,6 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -835,7 +742,6 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -860,7 +766,6 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "--user fakeUser --password fakePass --token-value fakeToken " + "--cert-file-passphrase fakePassphrase --cert-key-file /fake/path", @@ -888,44 +793,6 @@ describe("Command Processor", () => { expect(logOutput).toContain("--user **** --password **** --token-value **** --cert-file-passphrase **** --cert-key-file ****"); }); - it("should handle an error thrown from the profile loader", async () => { - // Allocate the command processor - const processor: CommandProcessor = new CommandProcessor({ - envVariablePrefix: ENV_VAR_PREFIX, - fullDefinition: SAMPLE_COMPLEX_COMMAND, - definition: SAMPLE_COMMAND_REAL_HANDLER, - helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, - rootCommandName: SAMPLE_ROOT_COMMAND, - commandLine: "", - promptPhrase: "dummydummy" - }); - - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - CommandProfileLoader.loader = jest.fn((args) => { - throw new ImperativeError({ msg: "Profile loading failed!" }); - }); - - const parms: any = { - arguments: { _: ["check", "for", "banana"], $0: "", valid: true }, - responseFormat: "json", silent: true - }; - const commandResponse: ICommandResponse = await processor.invoke(parms); - - expect(commandResponse).toBeDefined(); - const stderrText = (commandResponse.stderr as Buffer).toString(); - expect(stderrText).toContain("Command Preparation Failed:"); - expect(stderrText).toContain("Profile loading failed!"); - expect(commandResponse.message).toEqual("Profile loading failed!"); - expect(commandResponse.error?.msg).toEqual("Profile loading failed!"); - expect(commandResponse.error?.additionalDetails).not.toBeDefined(); - }); - it("should handle not being able to instantiate the handler", async () => { // Allocate the command processor const processor: CommandProcessor = new CommandProcessor({ @@ -933,26 +800,11 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" }); - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - const parms: any = { arguments: { _: ["check", "for", "banana"], @@ -988,26 +840,11 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: commandDef, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" }); - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - const parms: any = { arguments: { _: ["check", "for", "banana"], @@ -1040,26 +877,11 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: commandDef, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" }); - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - const parms: any = { arguments: { _: ["check", "for", "banana"], @@ -1101,26 +923,11 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: commandDef, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" }); - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - const parms: any = { arguments: { _: ["check", "for", "banana"], @@ -1144,26 +951,11 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_REAL_HANDLER, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" }); - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - const parms: any = { arguments: { _: ["check", "for", "banana"], @@ -1188,82 +980,18 @@ describe("Command Processor", () => { expect(commandResponse.error?.additionalDetails).toEqual("More details!"); }); - it("should handle an imperative error thrown from the handler", async () => { - // Allocate the command processor - const processor: CommandProcessor = new CommandProcessor({ - envVariablePrefix: ENV_VAR_PREFIX, - fullDefinition: SAMPLE_COMPLEX_COMMAND, - definition: SAMPLE_COMMAND_REAL_HANDLER, - helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, - rootCommandName: SAMPLE_ROOT_COMMAND, - commandLine: "", - promptPhrase: "dummydummy" - }); - - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - - const parms: any = { - arguments: { - _: ["check", "for", "banana"], - $0: "", - valid: true, - throwImperative: true - }, - responseFormat: "json", - silent: true - }; - const commandResponse: ICommandResponse = await processor.invoke(parms); - expect(commandResponse).toBeDefined(); - const stderrText = (commandResponse.stderr as Buffer).toString(); - expect(stderrText).toContain("Handler threw an imperative error!"); - expect(stderrText).toContain("More details!"); - expect(commandResponse.message).toEqual("Handler threw an imperative error!"); - expect(commandResponse.error?.msg).toEqual("Handler threw an imperative error!"); - expect(commandResponse.error?.additionalDetails).toEqual("More details!"); - }); - - it("should handle an imperative error with JSON causeErrors using v3-format message", async () => { - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(true); - + it("should handle an imperative error with JSON causeErrors", async () => { // Allocate the command processor const processor: CommandProcessor = new CommandProcessor({ envVariablePrefix: ENV_VAR_PREFIX, fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_REAL_HANDLER, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" }); - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - const parms: any = { arguments: { _: ["check", "for", "banana"], @@ -1288,35 +1016,18 @@ describe("Command Processor", () => { expect(commandResponse.error?.additionalDetails).toEqual("More details!"); }); - it("should handle an imperative error with string causeErrors using v3-format message", async () => { - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(true); - + it("should handle an imperative error with string causeErrors", async () => { // Allocate the command processor const processor: CommandProcessor = new CommandProcessor({ envVariablePrefix: ENV_VAR_PREFIX, fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_REAL_HANDLER, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" }); - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - const parms: any = { arguments: { _: ["check", "for", "banana"], @@ -1348,26 +1059,11 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_REAL_HANDLER, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" }); - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - const parms: any = { arguments: { _: ["check", "for", "banana"], @@ -1402,77 +1098,11 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_REAL_HANDLER, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, - rootCommandName: SAMPLE_ROOT_COMMAND, - commandLine: "", - promptPhrase: "dummydummy" - }); - - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - - const parms: any = { - arguments: { - _: ["check", "for", "banana"], - $0: "", - valid: true, - rejectWithMessage: true - }, - responseFormat: "json", - silent: true - }; - const commandResponse: ICommandResponse = await processor.invoke(parms); - expect(commandResponse).toBeDefined(); - const stderrText = (commandResponse.stderr as Buffer).toString(); - expect(stderrText).toContain("Command Error:"); - expect(stderrText).toContain("Rejected with a message"); - expect(commandResponse.success).toEqual(false); - expect(commandResponse.exitCode).toEqual(1); - expect(commandResponse.message).toEqual("Rejected with a message"); - expect(commandResponse.error?.msg).toEqual("Rejected with a message"); - expect(commandResponse.error?.additionalDetails).not.toBeDefined(); - }); - - it("should handle a handler-error with a v3-format message", async () => { - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(true); - - // Allocate the command processor - const processor: CommandProcessor = new CommandProcessor({ - envVariablePrefix: ENV_VAR_PREFIX, - fullDefinition: SAMPLE_COMPLEX_COMMAND, - definition: SAMPLE_COMMAND_REAL_HANDLER, - helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" }); - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - const parms: any = { arguments: { _: ["check", "for", "banana"], @@ -1502,26 +1132,11 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_REAL_HANDLER, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" }); - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - const parms: any = { arguments: { _: ["check", "for", "banana"], @@ -1544,26 +1159,11 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_REAL_HANDLER, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" }); - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - const parms: any = { arguments: { _: ["check", "for", "banana"], @@ -1601,7 +1201,6 @@ describe("Command Processor", () => { ], }, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -1621,68 +1220,7 @@ describe("Command Processor", () => { expect(commandResponse.data.commandValues[parm1Key]).toBe(parm1Value); }); - it("should display input value for simple parm when --show-inputs-only flag is set and v1 profile exists", async () => { - - // values to test - const parm1Key = `parm1`; - const parm1Value = `value1`; - - // Allocate the command processor - const processor: CommandProcessor = new CommandProcessor({ - envVariablePrefix: ENV_VAR_PREFIX, - fullDefinition: SAMPLE_CMD_WITH_OPTS_AND_PROF, // `group action` - definition: { // `object` - name: "banana", - description: "The banana command", - type: "command", - handler: __dirname + "/__model__/TestCmdHandler", - options: [ - { - name: parm1Key, - type: "string", - description: "The first parameter", - } - ], - }, - helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, - rootCommandName: SAMPLE_ROOT_COMMAND, - commandLine: "", - promptPhrase: "dummydummy" - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - return; - } - }; - }); - - // return the "fake" args object with values from profile - CliUtils.getOptValueFromProfiles = jest.fn((cmdProfiles, profileDef, allOpts) => { - return { - color: "yellow" - }; - }); - - const parms: any = { - arguments: { - _: ["check", "for", "banana"], - $0: "", - [parm1Key]: parm1Value, - valid: true, - showInputsOnly: true, - }, - silent: true - }; - const commandResponse: ICommandResponse = await processor.invoke(parms); - expect(commandResponse.data.locations[0]).toContain('home'); - expect(commandResponse.data.profileVersion).toBe('v1'); - }); - - it("should display input value for simple parm when --show-inputs-only flag is set and v2 config exists", async () => { + it("should display input value for simple parm when --show-inputs-only flag is set and team config exists", async () => { // values to test const parm1Key = `parm1`; @@ -1753,20 +1291,10 @@ describe("Command Processor", () => { } }, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy", - config: ImperativeConfig.instance.config - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - return; - } - }; + config: ImperativeConfig.instance.config }); const parms: any = { @@ -1783,54 +1311,110 @@ describe("Command Processor", () => { expect(commandResponse.data.locations.length).toBeGreaterThan(0); expect(commandResponse.data.optionalProfiles[0]).toBe(`banana`); expect(commandResponse.data.requiredProfiles).toBeUndefined(); - expect(commandResponse.data.profileVersion).toBe('v2'); }); - it("should mask input value for a default secure parm when --show-inputs-only flag is set", async () => { // values to test - const parm1Key = `user`; - const parm1Value = `secret`; + const secretParmKey = `brownSpots`; + const secretParmValue = true; const secure = `(secure value)`; + await setupConfigToLoad({ + "profiles": { + "fruit": { + "properties": { + "origin": "California" + }, + "profiles": { + "apple": { + "type": "fruit", + "properties": { + "color": "red" + } + }, + "banana": { + "type": "fruit", + "properties": { + "color": "yellow", + secretParmKey : secretParmValue + }, + "secure": [ + secretParmKey + ] + }, + "orange": { + "type": "fruit", + "properties": { + "color": "orange" + } + } + } + } + }, + "defaults": { + "fruit": "fruit.apple", + "banana": "fruit.banana" + }, + "plugins": [ + "@zowe/fruit-for-imperative" + ] + }); + // Allocate the command processor const processor: CommandProcessor = new CommandProcessor({ envVariablePrefix: ENV_VAR_PREFIX, - fullDefinition: SAMPLE_COMPLEX_COMMAND, // `group action` - definition: { // `object` + fullDefinition: SAMPLE_CMD_WITH_OPTS_AND_PROF, // `group action` + definition: { name: "banana", description: "The banana command", type: "command", - handler: __dirname + "/__model__/TestCmdHandler", + handler: __dirname + "/__model__/TestArgHandler", options: [ { - name: parm1Key, + name: "boolean-opt", + type: "boolean", + description: "A boolean option.", + }, + { + name: "color", type: "string", - description: "The first parameter", - } + description: "The banana color.", + required: true + }, + { + name: secretParmKey, + type: "boolean", + description: "Whether or not the banana has brown spots" + }, ], + profile: { + optional: ["banana"] + } }, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", - promptPhrase: "dummydummy" + promptPhrase: "dummydummy", + config: ImperativeConfig.instance.config }); const parms: any = { arguments: { _: ["check", "for", "banana"], $0: "", - [parm1Key]: parm1Value, + [secretParmKey]: secretParmValue, valid: true, showInputsOnly: true, }, silent: true }; + const commandResponse: ICommandResponse = await processor.invoke(parms); - expect(commandResponse.data.commandValues[parm1Key]).toBe(secure); - expect(commandResponse.stderr.toString()).toContain(`Some inputs are not displayed`); + expect(commandResponse.data.locations.length).toBeGreaterThan(0); + expect(commandResponse.data.optionalProfiles[0]).toBe(`banana`); + expect(commandResponse.data.commandValues[secretParmKey]).toBe(secure); + expect(commandResponse.data.requiredProfiles).toBeUndefined(); }); it.each(LoggerUtils.SECURE_PROMPT_OPTIONS)("should mask input value for secure parm %s when --show-inputs-only flag is set", async (propName) => { @@ -1872,13 +1456,15 @@ describe("Command Processor", () => { } }, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy", config: ImperativeConfig.instance.config }); + // return the "fake" args object with values from profile + jest.spyOn(CliUtils, "getOptValuesFromConfig").mockReturnValueOnce({}); + const parms: any = { arguments: { _: ["check", "for", "banana"], @@ -1920,7 +1506,6 @@ describe("Command Processor", () => { ], }, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -1950,7 +1535,6 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_REAL_HANDLER, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy", @@ -1962,20 +1546,6 @@ describe("Command Processor", () => { } }); - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - jest.spyOn(process, "chdir"); const mockConfigReload = jest.fn(); jest.spyOn(ImperativeConfig, "instance", "get").mockReturnValue({ @@ -2017,7 +1587,6 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_REAL_HANDLER, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy", @@ -2029,20 +1598,6 @@ describe("Command Processor", () => { } }); - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - jest.spyOn(process, "chdir"); const mockConfigReload = jest.fn(); jest.spyOn(ImperativeConfig, "instance", "get").mockReturnValue({ @@ -2085,32 +1640,14 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_CMD_WITH_OPTS_AND_PROF, definition: SAMPLE_COMMAND_REAL_HANDLER_WITH_OPT, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY_WITH_PROPS, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", - promptPhrase: "dummydummy" - }); - - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - return; - } - }; + promptPhrase: "dummydummy", + config: ImperativeConfig.instance.config }); // return the "fake" args object with values from profile - CliUtils.getOptValueFromProfiles = jest.fn((cmdProfiles, profileDef, allOpts) => { - return { - color: "yellow" - }; - }); + const getOptValuesSpy = jest.spyOn(CliUtils, "getOptValuesFromConfig").mockReturnValueOnce({ color: "yellow" }); const parms: any = { arguments: { @@ -2122,7 +1659,7 @@ describe("Command Processor", () => { }; const commandResponse: ICommandResponse = await processor.invoke(parms); - expect(CliUtils.getOptValueFromProfiles).toHaveBeenCalledTimes(1); + expect(getOptValuesSpy).toHaveBeenCalledTimes(1); expect(commandResponse.stdout.toString()).toMatchSnapshot(); expect(commandResponse).toBeDefined(); expect(commandResponse).toMatchSnapshot(); @@ -2134,30 +1671,13 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_CMD_WITH_OPTS_AND_PROF, definition: SAMPLE_COMMAND_REAL_HANDLER_WITH_DEFAULT_OPT, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY_WITH_PROPS, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" }); - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - return; - } - }; - }); - // return the "fake" args object with values from profile - CliUtils.getOptValueFromProfiles = jest.fn((cmdProfiles, profileDef, allOpts) => { - return {}; - }); + jest.spyOn(CliUtils, "getOptValuesFromConfig").mockReturnValueOnce({}); const parms: any = { arguments: { @@ -2180,32 +1700,14 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_CMD_WITH_OPTS_AND_PROF, definition: SAMPLE_COMMAND_REAL_HANDLER_WITH_POS_OPT, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY_WITH_PROPS, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", - promptPhrase: "dummydummy" - }); - - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - return; - } - }; + promptPhrase: "dummydummy", + config: ImperativeConfig.instance.config }); // return the "fake" args object with values from profile - CliUtils.getOptValueFromProfiles = jest.fn((cmdProfiles, profileDef, allOpts) => { - return { - color: "yellow" - }; - }); + const getOptValuesSpy = jest.spyOn(CliUtils, "getOptValuesFromConfig").mockReturnValueOnce({ color: "yellow" }); const parms: any = { arguments: { @@ -2217,7 +1719,7 @@ describe("Command Processor", () => { }; const commandResponse: ICommandResponse = await processor.invoke(parms); - expect(CliUtils.getOptValueFromProfiles).toHaveBeenCalledTimes(1); + expect(getOptValuesSpy).toHaveBeenCalledTimes(1); expect(commandResponse.stdout.toString()).toMatchSnapshot(); expect(commandResponse).toBeDefined(); expect(commandResponse).toMatchSnapshot(); @@ -2229,32 +1731,14 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_CMD_WITH_OPTS_AND_PROF, definition: SAMPLE_COMMAND_REAL_HANDLER_WITH_POS_OPT, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY_WITH_PROPS, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", - promptPhrase: "dummydummy" - }); - - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - return; - } - }; + promptPhrase: "dummydummy", + config: ImperativeConfig.instance.config }); // return the "fake" args object with values from profile - CliUtils.getOptValueFromProfiles = jest.fn((cmdProfiles, profileDef, allOpts) => { - return { - color: "yellow" - }; - }); + const getOptValuesSpy = jest.spyOn(CliUtils, "getOptValuesFromConfig").mockReturnValueOnce({ color: "yellow" }); const parms: any = { arguments: { @@ -2267,7 +1751,7 @@ describe("Command Processor", () => { }; const commandResponse: ICommandResponse = await processor.invoke(parms); - expect(CliUtils.getOptValueFromProfiles).toHaveBeenCalledTimes(1); + expect(getOptValuesSpy).toHaveBeenCalledTimes(1); expect(commandResponse.stdout.toString()).toMatchSnapshot(); expect(commandResponse).toBeDefined(); expect(commandResponse).toMatchSnapshot(); @@ -2279,32 +1763,14 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_CMD_WITH_OPTS_AND_PROF, definition: SAMPLE_COMMAND_REAL_HANDLER_WITH_OPT, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY_WITH_PROPS, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", - promptPhrase: "dummydummy" - }); - - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - return; - } - }; + promptPhrase: "dummydummy", + config: ImperativeConfig.instance.config }); // return the "fake" args object with values from profile - CliUtils.getOptValueFromProfiles = jest.fn((cmdProfiles, profileDef, allOpts) => { - return { - color: "yellow" - }; - }); + const getOptValuesSpy = jest.spyOn(CliUtils, "getOptValuesFromConfig").mockReturnValueOnce({ color: "yellow" }); const parms: any = { arguments: { @@ -2317,7 +1783,7 @@ describe("Command Processor", () => { }; const commandResponse: ICommandResponse = await processor.invoke(parms); - expect(CliUtils.getOptValueFromProfiles).toHaveBeenCalledTimes(1); + expect(getOptValuesSpy).toHaveBeenCalledTimes(1); expect(commandResponse.stdout.toString()).toMatchSnapshot(); expect(commandResponse).toBeDefined(); expect(commandResponse).toMatchSnapshot(); @@ -2330,7 +1796,6 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMPLEX_COMMAND, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -2348,7 +1813,6 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_WIH_NO_HANDLER, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -2369,26 +1833,11 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_REAL_HANDLER, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" }); - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - const parms: any = { arguments: { _: [], @@ -2414,26 +1863,11 @@ describe("Command Processor", () => { fullDefinition: SAMPLE_COMPLEX_COMMAND, definition: SAMPLE_COMMAND_REAL_HANDLER, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" }); - // Mock read stdin - (SharedOptions.readStdinIfRequested as any) = jest.fn((args, response, type) => { - // Nothing to do - }); - - // Mock the profile loader - (CommandProfileLoader.loader as any) = jest.fn((args) => { - return { - loadProfiles: (profArgs: any) => { - // Nothing to do - } - }; - }); - const parms: any = { arguments: { _: [], @@ -2497,7 +1931,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -2524,7 +1957,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -2551,7 +1983,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_DEFINITION_WITH_EXAMPLES, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy" @@ -2624,7 +2055,6 @@ describe("Command Processor", () => { envVariablePrefix: ENV_VAR_PREFIX, definition: SAMPLE_COMMAND_REAL_HANDLER_WITH_OPT, helpGenerator: FAKE_HELP_GENERATOR, - profileManagerFactory: FAKE_PROFILE_MANAGER_FACTORY, rootCommandName: SAMPLE_ROOT_COMMAND, commandLine: "", promptPhrase: "dummydummy", @@ -2633,22 +2063,132 @@ describe("Command Processor", () => { }); it("should find profile that matches name specified in arguments", async () => { - const commandPrepared = await (processor as any).prepare(null, { + const preparedArgs = await (processor as any).prepare(null, { "banana-profile": "ripe" }); - expect(commandPrepared.args.color).toBe("yellow"); + expect(preparedArgs.color).toBe("yellow"); }); it("should find profile with type prefix that matches name specified in arguments", async () => { - const commandPrepared = await (processor as any).prepare(null, { + const preparedArgs = await (processor as any).prepare(null, { "banana-profile": "old" }); - expect(commandPrepared.args.color).toBe("brown"); + expect(preparedArgs.color).toBe("brown"); }); it("should find default profile that matches type", async () => { - const commandPrepared = await (processor as any).prepare(null, {}); - expect(commandPrepared.args.color).toBe("green"); + const preparedArgs = await (processor as any).prepare(null, {}); + expect(preparedArgs.color).toBe("green"); + }); + }); + + describe("prompting", () => { + const invokeParms: any = { + arguments: { + _: ["check", "for", "banana"], + $0: "", + valid: true + }, + silent: true + }; + function buildProcessor(definition: ICommandDefinition): CommandProcessor { + return new CommandProcessor({ + envVariablePrefix: ENV_VAR_PREFIX, + fullDefinition: SAMPLE_CMD_WITH_OPTS_AND_PROF, + definition, + helpGenerator: FAKE_HELP_GENERATOR, + rootCommandName: SAMPLE_ROOT_COMMAND, + commandLine: "", + promptPhrase: "please" + }); + } + + it("should prompt for missing positional with string type", async () => { + // Allocate the command processor + const processor = buildProcessor(SAMPLE_COMMAND_REAL_HANDLER_WITH_POS_OPT); + + const promptMock = jest.fn().mockResolvedValue("yellow"); + jest.spyOn(CommandResponse.prototype, "console", "get").mockReturnValueOnce({ + prompt: promptMock + } as any); + + invokeParms.arguments.color = "please"; + const commandResponse: ICommandResponse = await processor.invoke(invokeParms); + expect(commandResponse).toBeDefined(); + expect(promptMock).toHaveBeenCalledTimes(1); + expect(promptMock.mock.calls[0][0]).toContain(`Please enter "color"`); + expect(invokeParms.arguments.color).toBe("yellow"); + }); + + it("should prompt for missing positional with array type", async () => { + // Allocate the command processor + const processor = buildProcessor({ + ...SAMPLE_COMMAND_REAL_HANDLER_WITH_POS_OPT, + positionals: [ + { + name: "color", + type: "array", + description: "The banana colors.", + required: true + } + ], + }); + + const promptMock = jest.fn().mockResolvedValue("yellow brown"); + jest.spyOn(CommandResponse.prototype, "console", "get").mockReturnValueOnce({ + prompt: promptMock + } as any); + + invokeParms.arguments.color = ["please"]; + const commandResponse: ICommandResponse = await processor.invoke(invokeParms); + expect(commandResponse).toBeDefined(); + expect(promptMock).toHaveBeenCalledTimes(1); + expect(promptMock.mock.calls[0][0]).toContain(`Please enter "color"`); + expect(invokeParms.arguments.color).toEqual(["yellow", "brown"]); + }); + + it("should prompt for missing option with string type", async () => { + // Allocate the command processor + const processor = buildProcessor(SAMPLE_COMMAND_REAL_HANDLER_WITH_OPT); + + const promptMock = jest.fn().mockResolvedValue("yellow"); + jest.spyOn(CommandResponse.prototype, "console", "get").mockReturnValueOnce({ + prompt: promptMock + } as any); + + invokeParms.arguments.color = "please"; + const commandResponse: ICommandResponse = await processor.invoke(invokeParms); + expect(commandResponse).toBeDefined(); + expect(promptMock).toHaveBeenCalledTimes(1); + expect(promptMock.mock.calls[0][0]).toContain(`Please enter "color"`); + expect(invokeParms.arguments.color).toBe("yellow"); + }); + + it("should prompt for missing option with array type", async () => { + // Allocate the command processor + const processor = buildProcessor({ + ...SAMPLE_COMMAND_REAL_HANDLER_WITH_OPT, + options: [ + { + name: "color", + type: "array", + description: "The banana colors.", + required: true + } + ], + }); + + const promptMock = jest.fn().mockResolvedValue("yellow brown"); + jest.spyOn(CommandResponse.prototype, "console", "get").mockReturnValueOnce({ + prompt: promptMock + } as any); + + invokeParms.arguments.color = ["please"]; + const commandResponse: ICommandResponse = await processor.invoke(invokeParms); + expect(commandResponse).toBeDefined(); + expect(promptMock).toHaveBeenCalledTimes(1); + expect(promptMock.mock.calls[0][0]).toContain(`Please enter "color"`); + expect(invokeParms.arguments.color).toEqual(["yellow", "brown"]); }); }); }); diff --git a/packages/imperative/src/cmd/__tests__/__snapshots__/CommandProcessor.unit.test.ts.snap b/packages/imperative/src/cmd/__tests__/__snapshots__/CommandProcessor.unit.test.ts.snap index eec473605e..0ba333dff1 100644 --- a/packages/imperative/src/cmd/__tests__/__snapshots__/CommandProcessor.unit.test.ts.snap +++ b/packages/imperative/src/cmd/__tests__/__snapshots__/CommandProcessor.unit.test.ts.snap @@ -131,8 +131,6 @@ exports[`Command Processor should detect no command definition supplied 1`] = `" exports[`Command Processor should detect no help generator supplied 1`] = `"Expect Error: Command Processor Error: No help generator supplied."`; -exports[`Command Processor should detect no profile manager factory supplied 1`] = `"Expect Error: Command Processor Error: No profile manager factory supplied."`; - exports[`Command Processor should detect no root command supplied 1`] = `"Expect Error: Command Processor Error: No root command supplied."`; exports[`Command Processor should detect that no parameters have been supplied 1`] = `"Expect Error: Command Processor Error: No parameters supplied to constructor."`; diff --git a/packages/imperative/src/cmd/__tests__/help/WebHelpGenerator.unit.test.ts b/packages/imperative/src/cmd/__tests__/help/WebHelpGenerator.unit.test.ts index 07f565ce90..814a3298c2 100644 --- a/packages/imperative/src/cmd/__tests__/help/WebHelpGenerator.unit.test.ts +++ b/packages/imperative/src/cmd/__tests__/help/WebHelpGenerator.unit.test.ts @@ -23,8 +23,6 @@ import { ICommandDefinition } from "../../../cmd/src/doc/ICommandDefinition"; describe("WebHelpGenerator", () => { describe("buildHelp", () => { - // eslint-disable-next-line deprecation/deprecation - const mainModule = process.mainModule; let moduleFileNm: string; let cliHome: string; let configForHelp: IImperativeConfig; @@ -102,21 +100,12 @@ describe("WebHelpGenerator", () => { rimraf.sync(cliHome); - /* process.mainModule.filename was null, so we must give it a value. - * mainModule is a getter of a property, so we mock the property. - */ - // eslint-disable-next-line deprecation/deprecation - (process.mainModule as any) = { - filename: moduleFileNm - }; - // imperative.init does all the setup for WebHelp to be run await Imperative.init(configForHelp); + ImperativeConfig.instance.rootCommandName = moduleFileNm; }); afterAll(() => { - // eslint-disable-next-line deprecation/deprecation - process.mainModule = mainModule; rimraf.sync(cliHome); }); diff --git a/packages/imperative/src/cmd/__tests__/help/WebHelpManager.unit.test.ts b/packages/imperative/src/cmd/__tests__/help/WebHelpManager.unit.test.ts index 111465a9bc..8ab28c75fa 100644 --- a/packages/imperative/src/cmd/__tests__/help/WebHelpManager.unit.test.ts +++ b/packages/imperative/src/cmd/__tests__/help/WebHelpManager.unit.test.ts @@ -41,8 +41,6 @@ describe("WebHelpManager", () => { const webHelpDirNm = path.join(mockCliHome, "web-help"); const impCfg: ImperativeConfig = ImperativeConfig.instance; const cmdReponse = new CommandResponse({ silent: false }); - // eslint-disable-next-line deprecation/deprecation - const mainModule = process.mainModule; let opener: any; let instPluginsFileNm: string; let oldProcessEnv: any; @@ -53,14 +51,6 @@ describe("WebHelpManager", () => { rimraf.sync(mockCliHome); - /* getResolvedCmdTree calls getCallerLocation, and we need it to return some string. - * getCallerLocation is a getter of a property, so we mock the property. - */ - // eslint-disable-next-line deprecation/deprecation - (process.mainModule as any) = { - filename: "FakeCli" - }; - // cliHome is a getter of a property, so mock the property Object.defineProperty(impCfg, "cliHome", { configurable: true, @@ -71,6 +61,7 @@ describe("WebHelpManager", () => { // imperative.init does all the setup for WebHelp to be run await Imperative.init(configForHelp); + ImperativeConfig.instance.rootCommandName = "FakeCli"; }); beforeEach(() => { @@ -83,8 +74,6 @@ describe("WebHelpManager", () => { }); afterAll(() => { - // eslint-disable-next-line deprecation/deprecation - process.mainModule = mainModule; rimraf.sync(mockCliHome); }); diff --git a/packages/imperative/src/cmd/__tests__/help/__snapshots__/AbstractHelpGenerator.unit.test.ts.snap b/packages/imperative/src/cmd/__tests__/help/__snapshots__/AbstractHelpGenerator.unit.test.ts.snap index d3c97a382b..226ec1565e 100644 --- a/packages/imperative/src/cmd/__tests__/help/__snapshots__/AbstractHelpGenerator.unit.test.ts.snap +++ b/packages/imperative/src/cmd/__tests__/help/__snapshots__/AbstractHelpGenerator.unit.test.ts.snap @@ -76,6 +76,7 @@ InheritedHelpGenerator { "category": "imperative", "initStatus": false, "mJsLogger": Logger { + "callStackSkipIndex": 0, "category": "imperative", "context": Object {}, "parseCallStack": [Function], @@ -132,6 +133,7 @@ InheritedHelpGenerator { "category": "imperative", "initStatus": false, "mJsLogger": Logger { + "callStackSkipIndex": 0, "category": "imperative", "context": Object {}, "parseCallStack": [Function], diff --git a/packages/imperative/src/cmd/__tests__/help/__snapshots__/DefaultHelpGenerator.unit.test.ts.snap b/packages/imperative/src/cmd/__tests__/help/__snapshots__/DefaultHelpGenerator.unit.test.ts.snap index 765e00791b..48632b0171 100644 --- a/packages/imperative/src/cmd/__tests__/help/__snapshots__/DefaultHelpGenerator.unit.test.ts.snap +++ b/packages/imperative/src/cmd/__tests__/help/__snapshots__/DefaultHelpGenerator.unit.test.ts.snap @@ -11,7 +11,7 @@ exports[`Default Help Generator help text builder buildUsageDiagram test 1`] = ` exports[`Default Help Generator help text builder buildUsageDiagram test 2`] = `"test-help a_experimental_parent hello [options]"`; exports[`Default Help Generator help text builder buildUsageDiagram test 3`] = ` -"test-help child +"test-help a_experimental_parent child Where is one of the following:" `; @@ -162,7 +162,7 @@ exports[`Default Help Generator help text builder getGroupHelpText test 2`] = ` USAGE ----- - test-help child + test-help a_experimental_parent child Where is one of the following: @@ -415,7 +415,7 @@ exports[`Default Help Generator help text builder should getCommandHelpText with USAGE ----- - test-help hello [options] + test-help a_experimental_parent hello [options] GLOBAL OPTIONS -------------- diff --git a/packages/imperative/src/cmd/__tests__/profiles/CliProfileManager.credentials.unit.test.ts b/packages/imperative/src/cmd/__tests__/profiles/CliProfileManager.credentials.unit.test.ts deleted file mode 100644 index 0e57e741ce..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/CliProfileManager.credentials.unit.test.ts +++ /dev/null @@ -1,633 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { TestLogger } from "../../../../__tests__/src/TestLogger"; -import { ProfileIO } from "../../../profiles/src/utils/ProfileIO"; -import { CliProfileManager } from "../../src/profiles/CliProfileManager"; -import { IProfile } from "../../../profiles/src/doc/definition/IProfile"; -import { - ONLY_ORANGE_WITH_CREDENTIALS, - SECURE_ORANGE_PROFILE_TYPE, - TEST_PROFILE_ROOT_DIR -} from "../../../profiles/__tests__/TestConstants"; -import { CredentialManagerFactory, DefaultCredentialManager } from "../../../security"; -import { BasicProfileManager } from "../../../profiles/src/BasicProfileManager"; -import { ProfilesConstants, ISaveProfile, IProfileSaved } from "../../../profiles"; - -jest.mock("../../../profiles/src/utils/ProfileIO"); -jest.mock("../../../security/src/DefaultCredentialManager"); - -// TODO: Some of these tests are not completely isolated, some may cause others to fail depending on mocks - -// **NOTE:** DefaultCredentialManager is mocked in such a way that the constructor parameters don't matter here. -// **NOTE:** Check the mocked file for what is actually used. - -describe("Cli Profile Manager", () => { - let writtenProfile: any; - - ProfileIO.writeProfile = jest.fn((fullFilePath: string, profile: IProfile) => { - writtenProfile = profile; - }); - - afterEach(() => { - writtenProfile = undefined; // clear any saved profile to not pollute results across tests - }); - - describe("Credential Manager functionality", () => { - let prof: CliProfileManager; - let parms: any; - const securelyStored = ProfilesConstants.PROFILES_OPTION_SECURELY_STORED + " dummy manager"; - const credentialManagerErrorMessage = /(Unable to).*(the secure field)/; - - const user = "username"; - const pass = "password"; - const phone = "{\"a\":\"b\"}"; - const code = 0; - const phrase = "phrase"; - const set = ["a1,a2", "b2"]; - const flag = false; - const minime = "mini-me"; - const name = "My-secure-orange"; - const description = "A secure orange"; - - beforeEach(() => { - prof = new CliProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_ORANGE_WITH_CREDENTIALS, - type: SECURE_ORANGE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - // We need to define parms every time since implementation explicitly deletes the username and password properties from memory - parms = { - name, - profile: { - description: "A secure orange" - }, - overwrite: false, - args: { - user, - phone, - code, - phrase, - set, - flag, - minime - } - }; - - prof.setDefault = jest.fn(); - }); - - describe("Save operation", () => { - it("should save credentials and store a profile with a constant string value for secure properties", async () => { - const dummyManager = new DefaultCredentialManager("dummy"); - dummyManager.save = jest.fn(); - Object.defineProperty(CredentialManagerFactory, "manager", {get: jest.fn().mockReturnValue(dummyManager)}); - Object.defineProperty(CredentialManagerFactory, "initialized", {get: jest.fn().mockReturnValue(true)}); - - const tempProf: any = { - username: user, - password: undefined, - secureBox: { - myCode: securelyStored, - myFlag: securelyStored, - myMiniBox: securelyStored, - myPhone: securelyStored, - myPhrase: securelyStored, - mySet: securelyStored, - myEmptyMiniBox: null, - } - }; - - jest.spyOn(BasicProfileManager.prototype, "saveProfile" as any).mockImplementation((tParms: ISaveProfile | any) => { - return { - overwritten: tParms.overwrite, - profile: tParms.profile - }; - }); - - const result = await prof.save(parms); - - // Parms should be successfully deleted form memory - expect(parms.args).toBeUndefined(); - - // BasicProfileManager should be called to save the profile with the given options - expect((BasicProfileManager.prototype as any).saveProfile).toHaveBeenCalledWith({ - name, - type: "secure-orange", - overwrite: false, - profile: tempProf - }); - - // Should have saved every secure property as a constant string - expect(result.profile).toMatchObject(tempProf); - - // writtenProfile === undefined since BasicProfileManager gets mocked and doesn't call ProfileIO.writeProfile - expect(writtenProfile).toBeUndefined(); - - (BasicProfileManager.prototype as any).saveProfile.mockRestore(); - }); - - it("should not invoke the credential manager if it has not been initialized", async () => { - // We'll use a dummy credential manager in the test - but set initialized to "false" - this way we can use - // Jest expect.toHaveBeenCalledTimes(0) - const dummyManager = new DefaultCredentialManager("dummy"); - dummyManager.save = jest.fn(); - Object.defineProperty(CredentialManagerFactory, "manager", {get: jest.fn().mockReturnValue(dummyManager)}); - Object.defineProperty(CredentialManagerFactory, "initialized", {get: jest.fn().mockReturnValue(false)}); - - const tempProf: any = { - username: user, - password: null, - secureBox: { - myCode: securelyStored, - myFlag: securelyStored, - myMiniBox: securelyStored, - myPhone: securelyStored, - myPhrase: securelyStored, - mySet: securelyStored, - myEmptyMiniBox: null, - } - }; - - jest.spyOn(BasicProfileManager.prototype, "saveProfile" as any).mockImplementation((tParms: ISaveProfile | any) => { - return { - overwritten: tParms.overwrite, - profile: tParms.profile - }; - }); - - await prof.save(parms); - - // Parms should be successfully deleted form memory - expect(parms.args).toBeUndefined(); - - // writtenProfile === undefined since BasicProfileManager gets mocked and doesn't call ProfileIO.writeProfile - expect(writtenProfile).toBeUndefined(); - - // Expect the credential manager save to have NOT been called - expect(dummyManager.save).toHaveBeenCalledTimes(0); - - (BasicProfileManager.prototype as any).saveProfile.mockRestore(); - }); - - it("should save credentials without erroring the credential manager if there are no secure credentials to save", async () => { - // We'll use a dummy credential manager in the test - but set initialized to "false" - this way we can use - // Jest expect.toHaveBeenCalledTimes(0) - const dummyManager = new DefaultCredentialManager("dummy"); - dummyManager.save = jest.fn(); - dummyManager.delete = jest.fn(() => { - throw new Error("This is a dummy error that is thrown"); - }); - Object.defineProperty(CredentialManagerFactory, "manager", {get: jest.fn().mockReturnValue(dummyManager)}); - Object.defineProperty(CredentialManagerFactory, "initialized", {get: jest.fn().mockReturnValue(true)}); - - const tempProf: any = { - username: user, - password: undefined, - secureBox: { - myCode: undefined, - myFlag: undefined, - myMiniBox: null, - myPhone: undefined, - myPhrase: undefined, - mySet: undefined, - myEmptyMiniBox: null, - } - }; - - parms.args.phone = undefined; - parms.args.code = undefined; - parms.args.phrase = undefined; - parms.args.set = undefined; - parms.args.flag = undefined; - parms.args.minime = undefined; - - jest.spyOn(BasicProfileManager.prototype, "saveProfile" as any).mockImplementation((tParms: ISaveProfile | any) => { - return { - overwritten: tParms.overwrite, - profile: tParms.profile - }; - }); - - let result: IProfileSaved; - let errorMessage: string; - try { - result = await prof.save(parms); - } catch (err) { - errorMessage = err.message; - } - // Parms should be successfully deleted from memory - expect(parms.args).toBeUndefined(); - expect(errorMessage).toBeUndefined(); - - // BasicProfileManager should be called to save the profile with the given options - expect((BasicProfileManager.prototype as any).saveProfile).toHaveBeenCalledWith({ - name, - type: "secure-orange", - overwrite: false, - profile: tempProf - }); - - // Should have saved every secure property as a constant string - expect(result.profile).toMatchObject(tempProf); - - // Expect the credential manager save to not have been called - // and delete to have been called a few (6) times, but still work - // even if it threw an error. - expect(dummyManager.save).toHaveBeenCalledTimes(0); - expect(dummyManager.delete).toHaveBeenCalledTimes(6); - - (BasicProfileManager.prototype as any).saveProfile.mockRestore(); - }); - - it("should fail if the Credential Manager throws an error", async () => { - const dummyManager = new DefaultCredentialManager("dummy"); - dummyManager.save = jest.fn(() => { - throw new Error("dummy error"); - }); - Object.defineProperty(CredentialManagerFactory, "manager", {get: jest.fn().mockReturnValue(dummyManager)}); - Object.defineProperty(CredentialManagerFactory, "initialized", {get: jest.fn().mockReturnValue(true)}); - - - let errorMessage = ""; - try { - await prof.save(parms); - } catch (err) { - errorMessage = err.message; - } - - expect(errorMessage).toMatch(credentialManagerErrorMessage); - }); - }); - - describe("Update operation", () => { - const tempProf: any = { - description, - username: user, - password: undefined, - secureBox: { - myCode: securelyStored, - myFlag: securelyStored, - myMiniBox: securelyStored, - myPhone: securelyStored, - myPhrase: securelyStored, - mySet: securelyStored, - myEmptyMiniBox: null, - } - }; - - it("should update credentials and store a profile with a constant string value for secure properties", async () => { - const dummyManager = new DefaultCredentialManager("dummy"); - const mockDeleteCreds = jest.fn(); - dummyManager.delete = mockDeleteCreds; - dummyManager.save = jest.fn(); - Object.defineProperty(CredentialManagerFactory, "manager", {get: jest.fn().mockReturnValue(dummyManager)}); - - jest.spyOn(BasicProfileManager.prototype, "saveProfile" as any).mockImplementation((tParms: ISaveProfile | any) => { - return { - overwritten: tParms.overwrite, - profile: tParms.profile - }; - }); - - jest.spyOn(CliProfileManager.prototype, "loadProfile" as any).mockReturnValue({ - profile: tempProf - }); - - const result = await prof.update(parms); - - // Parms should be successfully deleted form memory - expect(parms.args).toBeUndefined(); - - // BasicProfileManager should be called to save the profile with the given options - expect((BasicProfileManager.prototype as any).saveProfile).toHaveBeenCalledWith({ - name, - type: "secure-orange", - overwrite: true, - profile: tempProf, - updateDefault: false - }); - - // Should have updated every secure property as a constant string - expect(result.profile).toMatchObject(tempProf); - - // writtenProfile === undefined since BasicProfileManager gets mocked and doesn't call ProfileIO.writeProfile - expect(writtenProfile).toBeUndefined(); - - // Should have deleted credentials for password in case it was defined previously - expect(mockDeleteCreds).toHaveBeenCalledTimes(1); - expect(mockDeleteCreds.mock.calls[0][0]).toContain("password"); - - (CliProfileManager.prototype as any).loadProfile.mockRestore(); - (BasicProfileManager.prototype as any).saveProfile.mockRestore(); - }); - - it("should fail if the Credential Manager throws an error", async () => { - const dummyManager = new DefaultCredentialManager("dummy"); - dummyManager.save = jest.fn(() => { - throw new Error("dummy error"); - }); - Object.defineProperty(CredentialManagerFactory, "manager", {get: jest.fn().mockReturnValue(dummyManager)}); - - jest.spyOn(CliProfileManager.prototype, "loadProfile" as any).mockReturnValue({ - profile: tempProf - }); - - let errorMessage = ""; - try { - await prof.update(parms); - } catch (err) { - errorMessage = err.message; - } - - expect(errorMessage).toMatch(credentialManagerErrorMessage); - - (CliProfileManager.prototype as any).loadProfile.mockRestore(); - }); - }); - - describe("Load operation", () => { - const tempProf: any = { - name, - username: user, - password: null, - type: SECURE_ORANGE_PROFILE_TYPE, - secureBox: { - myCode: securelyStored, - myFlag: securelyStored, - myMiniBox: securelyStored, - myPhone: securelyStored, - myPhrase: securelyStored, - mySet: securelyStored, - myEmptyMiniBox: null, - } - }; - - it("should load credentials from a profile with constant string values for secure properties", async () => { - const dummyManager = new DefaultCredentialManager("dummy"); - dummyManager.load = jest.fn(async (propKey: string) => { - let ret: any = null; - if (propKey.indexOf("myCode") >= 0) { - ret = code; - } else if (propKey.indexOf("myFlag") >= 0) { - ret = flag; - } else if (propKey.indexOf("myMiniBox") >= 0) { - ret = {minime}; - } else if (propKey.indexOf("myPhone") >= 0) { - ret = phone; - } else if (propKey.indexOf("myPhrase") >= 0) { - ret = phrase; - } else if (propKey.indexOf("mySet") >= 0) { - ret = set; - } - return JSON.stringify(ret); - }); - Object.defineProperty(CredentialManagerFactory, "manager", {get: jest.fn().mockReturnValue(dummyManager)}); - - // same object but with real values - const copyTempProf = JSON.parse(JSON.stringify(tempProf)); - copyTempProf.secureBox = { - myCode: code, - myFlag: flag, - myMiniBox: {minime}, - myPhone: phone, - myPhrase: phrase, - mySet: set, - myEmptyMiniBox: null, - }; - - jest.spyOn(BasicProfileManager.prototype, "loadProfile" as any).mockReturnValue({ - profile: tempProf // This profile will be altered by reference with the real values by CliProfileManager.loadProfile - }); - - const result = await prof.load({name}); - - // BasicProfileManager should be called to save the profile with the given options - expect((BasicProfileManager.prototype as any).loadProfile).toHaveBeenCalledWith( - {name, failNotFound: true, loadDefault: false, loadDependencies: true} - ); - - // Compare to the modified-by-reference profile - expect(result.profile).toMatchObject(tempProf); - - // Compare to our manually modified profile - expect(result.profile).toMatchObject(copyTempProf); - - (BasicProfileManager.prototype as any).loadProfile.mockRestore(); - }); - - it("should not load credentials from a profile if noSecure is specified", async () => { - const dummyManager = new DefaultCredentialManager("dummy"); - dummyManager.load = jest.fn(async (propKey: string) => { - let ret: any = null; - if (propKey.indexOf("myCode") >= 0) { - ret = code; - } else if (propKey.indexOf("myFlag") >= 0) { - ret = flag; - } else if (propKey.indexOf("myMiniBox") >= 0) { - ret = {minime}; - } else if (propKey.indexOf("myPhone") >= 0) { - ret = phone; - } else if (propKey.indexOf("myPhrase") >= 0) { - ret = phrase; - } else if (propKey.indexOf("mySet") >= 0) { - ret = set; - } - return JSON.stringify(ret); - }); - Object.defineProperty(CredentialManagerFactory, "manager", {get: jest.fn().mockReturnValue(dummyManager)}); - Object.defineProperty(CredentialManagerFactory, "initialized", {get: jest.fn().mockReturnValue(true)}); - - // same object but with real values - const copyTempProf = JSON.parse(JSON.stringify(tempProf)); - copyTempProf.secureBox = { - myCode: ProfilesConstants.PROFILES_OPTION_SECURELY_STORED, - myFlag: ProfilesConstants.PROFILES_OPTION_SECURELY_STORED, - myMiniBox: ProfilesConstants.PROFILES_OPTION_SECURELY_STORED, - myPhone: ProfilesConstants.PROFILES_OPTION_SECURELY_STORED, - myPhrase: ProfilesConstants.PROFILES_OPTION_SECURELY_STORED, - mySet: ProfilesConstants.PROFILES_OPTION_SECURELY_STORED, - myEmptyMiniBox: null, - }; - - jest.spyOn(BasicProfileManager.prototype, "loadProfile" as any).mockReturnValue({ - profile: copyTempProf - }); - - const result = await prof.load({name, noSecure: true}); - - // BasicProfileManager should be called to save the profile with the given options - expect((BasicProfileManager.prototype as any).loadProfile).toHaveBeenCalledWith( - {name, failNotFound: true, loadDefault: false, loadDependencies: true, noSecure: true} - ); - - // Compare to the modified-by-reference profile - expect(result.profile).toMatchSnapshot(); - - (BasicProfileManager.prototype as any).loadProfile.mockRestore(); - }); - - it("should not attempt to load secure fields if no credential manager is present", async () => { - const dummyManager = new DefaultCredentialManager("dummy"); - dummyManager.load = jest.fn(async (propKey: string) => { - let ret: any = null; - if (propKey.indexOf("myCode") >= 0) { - ret = code; - } else if (propKey.indexOf("myFlag") >= 0) { - ret = flag; - } else if (propKey.indexOf("myMiniBox") >= 0) { - ret = {minime}; - } else if (propKey.indexOf("myPhone") >= 0) { - ret = phone; - } else if (propKey.indexOf("myPhrase") >= 0) { - ret = phrase; - } else if (propKey.indexOf("mySet") >= 0) { - ret = set; - } - return JSON.stringify(ret); - }); - - // Even, though it should not get the manager, we'll add a dummy to test if it gets called - const notCalledManager = jest.fn().mockReturnValue(dummyManager); - Object.defineProperty(CredentialManagerFactory, "manager", {get: notCalledManager}); - Object.defineProperty(CredentialManagerFactory, "initialized", {get: jest.fn().mockReturnValue(false)}); - - // same object but with real values - const copyTempProf = JSON.parse(JSON.stringify(tempProf)); - copyTempProf.secureBox = { - myCode: ProfilesConstants.PROFILES_OPTION_SECURELY_STORED, - myFlag: ProfilesConstants.PROFILES_OPTION_SECURELY_STORED, - myMiniBox: ProfilesConstants.PROFILES_OPTION_SECURELY_STORED, - myPhone: ProfilesConstants.PROFILES_OPTION_SECURELY_STORED, - myPhrase: ProfilesConstants.PROFILES_OPTION_SECURELY_STORED, - mySet: ProfilesConstants.PROFILES_OPTION_SECURELY_STORED, - myEmptyMiniBox: null, - }; - - jest.spyOn(BasicProfileManager.prototype, "loadProfile" as any).mockReturnValue({ - profile: copyTempProf - }); - - const result = await prof.load({name}); - - // BasicProfileManager should be called to save the profile with the given options - expect((BasicProfileManager.prototype as any).loadProfile).toHaveBeenCalledWith( - {name, failNotFound: true, loadDefault: false, loadDependencies: true} - ); - - // Compare to the modified-by-reference profile - expect(result.profile).toMatchSnapshot(); - - // The dummy manager should not have been called - expect(notCalledManager).toHaveBeenCalledTimes(0); - - (BasicProfileManager.prototype as any).loadProfile.mockRestore(); - }); - - it("should fail if the Credential Manager throws an error", async () => { - const dummyManager = new DefaultCredentialManager("dummy"); - dummyManager.load = jest.fn(() => { - throw new Error("dummy error"); - }); - Object.defineProperty(CredentialManagerFactory, "manager", {get: jest.fn().mockReturnValue(dummyManager)}); - Object.defineProperty(CredentialManagerFactory, "initialized", {get: jest.fn().mockReturnValue(true)}); - - jest.spyOn(BasicProfileManager.prototype, "loadProfile" as any).mockReturnValue({ - profile: tempProf - }); - - let errorMessage = ""; - try { - await prof.load({name}); - } catch (err) { - errorMessage = err.message; - } - - expect(errorMessage).toMatch(credentialManagerErrorMessage); - - (BasicProfileManager.prototype as any).loadProfile.mockRestore(); - }); - }); - - describe("Delete operation", () => { - it("should delete credentials and profile with with secure properties", async () => { - const dummyManager = new DefaultCredentialManager("dummy"); - dummyManager.delete = jest.fn(); - Object.defineProperty(CredentialManagerFactory, "manager", {get: jest.fn().mockReturnValue(dummyManager)}); - Object.defineProperty(CredentialManagerFactory, "initialized", {get: jest.fn().mockReturnValue(true)}); - - jest.spyOn(ProfileIO, "exists").mockReturnValue(true as any); - - jest.spyOn(BasicProfileManager.prototype, "deleteProfileFromDisk" as any).mockImplementation(() => "dummy-path"); - - const result = await prof.delete({name}); - - // BasicProfileManager should be called to save the profile with the given options - expect((BasicProfileManager.prototype as any).deleteProfileFromDisk).toHaveBeenCalledWith(name); - - // Should have saved every secure property as a constant string - expect(result.message).toMatch(/(Profile).*(delete).*(success).*/); - - (BasicProfileManager.prototype as any).deleteProfileFromDisk.mockRestore(); - (ProfileIO as any).exists.mockRestore(); - }); - - it("should not invoke the credential manager if it has not been initialized", async () => { - const dummyManager = new DefaultCredentialManager("dummy"); - dummyManager.delete = jest.fn(); - Object.defineProperty(CredentialManagerFactory, "manager", {get: jest.fn().mockReturnValue(dummyManager)}); - Object.defineProperty(CredentialManagerFactory, "initialized", {get: jest.fn().mockReturnValue(false)}); - - jest.spyOn(ProfileIO, "exists").mockReturnValue(true as any); - - jest.spyOn(BasicProfileManager.prototype, "deleteProfileFromDisk" as any).mockImplementation(() => "dummy-path"); - - const result = await prof.delete({name}); - - // BasicProfileManager should be called to save the profile with the given options - expect((BasicProfileManager.prototype as any).deleteProfileFromDisk).toHaveBeenCalledWith(name); - - // Should have saved every secure property as a constant string - expect(result.message).toMatch(/(Profile).*(delete).*(success).*/); - - // Should not have called the credential manager delete - expect(dummyManager.delete).toHaveBeenCalledTimes(0); - - (BasicProfileManager.prototype as any).deleteProfileFromDisk.mockRestore(); - (ProfileIO as any).exists.mockRestore(); - }); - - it("should fail if the Credential Manager throws an error", async () => { - const dummyManager = new DefaultCredentialManager("dummy"); - dummyManager.delete = jest.fn(() => { - throw new Error("dummy error"); - }); - Object.defineProperty(CredentialManagerFactory, "manager", {get: jest.fn().mockReturnValue(dummyManager)}); - Object.defineProperty(CredentialManagerFactory, "initialized", {get: jest.fn().mockReturnValue(true)}); - - jest.spyOn(ProfileIO, "exists").mockReturnValue(true as any); - - let errorMessage = ""; - try { - await prof.delete({name}); - } catch (err) { - errorMessage = err.message; - } - - expect(errorMessage).toMatch(credentialManagerErrorMessage); - - (ProfileIO as any).exists.mockRestore(); - }); - }); - }); -}); diff --git a/packages/imperative/src/cmd/__tests__/profiles/CliProfileManager.unit.test.ts b/packages/imperative/src/cmd/__tests__/profiles/CliProfileManager.unit.test.ts deleted file mode 100644 index f221f0dc64..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/CliProfileManager.unit.test.ts +++ /dev/null @@ -1,824 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ProfileUtils } from "../../../profiles/src/utils/ProfileUtils"; -import { TestLogger } from "../../../../__tests__/src/TestLogger"; -import { ICommandProfileTypeConfiguration } from "../../src/doc/profiles/definition/ICommandProfileTypeConfiguration"; -import { ProfileIO } from "../../../profiles/src/utils/ProfileIO"; -import { CliProfileManager } from "../../src/profiles/CliProfileManager"; -import { IProfile } from "../../../profiles/src/doc/definition/IProfile"; -import { inspect } from "util"; -import { ISaveProfileFromCliArgs } from "../../../profiles/src/doc/parms/ISaveProfileFromCliArgs"; -import { ImperativeError } from "../../../error/src/ImperativeError"; -import { PROFILE_TYPE } from "../../../../__tests__/src/packages/profiles/src/constants/BasicProfileManagerTestConstants"; -import { TEST_PROFILE_ROOT_DIR } from "../../../profiles/__tests__/TestConstants"; -import { IProfileLoaded } from "../../.."; - -jest.mock("../../../profiles/src/utils/ProfileIO"); -jest.mock("../../../security/src/DefaultCredentialManager"); - -describe("Cli Profile Manager", () => { - let writtenProfile: any; - - const originalSaveProfile = (CliProfileManager.prototype as any).saveProfile; - afterEach(() => { - (CliProfileManager.prototype as any).saveProfile = originalSaveProfile; - }); - ProfileIO.writeProfile = jest.fn((fullFilePath: string, profile: IProfile) => { - writtenProfile = profile; - }); - - ProfileIO.exists = jest.fn((path: string) => { - return path.indexOf("meta") === -1 ? path : undefined; - }); - - (ProfileIO.readMetaFile as any) = jest.fn((fullFilePath: string) => { - return { - defaultProfile: "mybana", - configuration: { - type: "", - schema: { - type: "object", - title: "test profile", - description: "test profile", - properties: { - sum: { - type: "number" - } - }, - required: ["sum"] - } - } - }; - }); - afterEach(() => { - writtenProfile = undefined; // clear any saved profile to not pollute results across tests - }); - - const profileDir = "dummy"; - const testLogger = TestLogger.getTestLogger(); - const profileTypeOne = "banana"; - const profileTypeTwo = "dependencies"; - const profileTypeThree = "differentOptions"; - const addTwoNumbersHandler = __dirname + "/profileHandlers/AddTwoNumbersHandler"; - const doNothingHandler = __dirname + "/profileHandlers/DoNothingHandler"; - const throwErrorHandler = __dirname + "/profileHandlers/ThrowErrorHandler"; - const getTypeConfigurations: () => ICommandProfileTypeConfiguration[] = () => { - return [{ - type: profileTypeOne, - schema: { - type: "object", - title: "test profile", - description: "test profile", - properties: { - sum: { - type: "number" - } - }, - required: ["sum"] - }, - }, { - type: profileTypeTwo, - schema: { - type: "object", - title: "profile with dependencies", - description: "profile with dependencies", - properties: {}, - required: ["dependencies"] - }, - dependencies: [ - {type: profileTypeOne, description: profileTypeOne + " dependency", required: true} - ] - }, - { - type: profileTypeThree, - title: "profile with different option names compare to schema fields", - schema: { - type: "object", - title: "test profile", - description: "test profile", - properties: { - property1: { - type: "number", - optionDefinition: { - name: "differentProperty1", - type: "number", - description: "property1" - } - }, - property2: { - type: "string", - optionDefinition: { - name: "differentProperty2", - type: "string", - description: "property2" - } - }, - hasChild: { - type: "object", - properties: { - hasGrandChild: { - type: "object", - properties: { - grandChild: { - optionDefinition: { - name: "myGrandChild", - type: "string", - description: "my grand child", - } - } - } - } - } - } - }, - required: ["property2"] - }, - }]; - }; - - it("should only load all profiles of the manager type if requested", async () => { - // Mock the profile IO functions - ProfileIO.getAllProfileNames = jest.fn((dir, ext, meta) => { - expect(dir).toContain(profileTypeOne); - return ["prof_banana"]; - }); - - // Create an instance of the manager - const configs = getTypeConfigurations(); - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - - // Load "all" profiles - const loads: IProfileLoaded[] = await manager.loadAll({typeOnly: true}); - expect(ProfileIO.getAllProfileNames).toHaveBeenCalledTimes(1); - }); - - it("should take a handler to create a profile from command line arguments, and " + - "the handler should be called and the resulting profile should have the created fields in it.", async () => { - const configs = getTypeConfigurations(); - - (ProfileIO.exists as any) = jest.fn(() => { - return true; // pretend the profile already exists - }); - - configs[0].createProfileFromArgumentsHandler = addTwoNumbersHandler; - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - const a = 1; - const b = 2; - const profileName = "myprofile"; - const saveResult = await manager.save({ - name: profileName, type: profileTypeOne, - profile: {}, - args: {_: [], $0: "test", a, b}, - overwrite: true - }); - testLogger.info("Save profile result: " + inspect(saveResult)); - expect(saveResult.profile.sum).toEqual(a + b); - expect(writtenProfile.sum).toEqual(a + b); - }); - - it("should take a handler to update a profile from command line arguments, and " + - "the handler should be called and the resulting profile should have the created fields in it.", async () => { - const configs = getTypeConfigurations(); - const oldSum = 55; - (ProfileIO.exists as any) = jest.fn(() => { - return true; // pretend the profile already exists - }); - ProfileIO.readProfileFile = jest.fn((fullFilePath: string, type: "string") => { - return {name: profileName, type: profileTypeOne, sum: oldSum}; - }); - configs[0].updateProfileFromArgumentsHandler = addTwoNumbersHandler; - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - const a = 1; - const b = 2; - const profileName = "myprofile"; - const saveResult = await manager.update({ - name: profileName, type: profileTypeOne, - profile: {}, - args: {_: [], $0: "test", a, b} - }); - testLogger.info("Update profile result: " + inspect(saveResult)); - expect(saveResult.profile.sum).toEqual(a + b); - }); - - it("should take a handler to create a profile from command line arguments, but if " + - "the profile handler does not add a field required by the schema, " + - "we should get a validation error", async () => { - const configs = getTypeConfigurations(); - (ProfileIO.exists as any) = jest.fn(() => { - return true; // pretend the profile already exists - }); - ProfileIO.writeProfile = jest.fn((fullFilePath: string, profile: IProfile) => { - writtenProfile = profile; - }); - configs[0].createProfileFromArgumentsHandler = doNothingHandler; - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - const a = 1; - const b = 2; - const profileName = "myprofile"; - try { - await manager.save({ - name: profileName, type: profileTypeOne, - profile: {}, - args: {_: [], $0: "test", a, b}, - overwrite: true - }); - } catch (e) { - expect(e.message).toContain("content"); - } - }); - - it("should still create a profile properly without providing args", async () => { - const configs = getTypeConfigurations(); - - (ProfileIO.exists as any) = jest.fn(() => { - return true; // pretend the profile already exists - }); - ProfileIO.writeProfile = jest.fn((fullFilePath: string, profile: IProfile) => { - writtenProfile = profile; - }); - configs[0].createProfileFromArgumentsHandler = doNothingHandler; - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - const profileName = "myprofile"; - let caughtError; - - try { - await manager.save({ - name: profileName, type: profileTypeOne, - profile: {sum: 55}, - overwrite: true - }); - } catch (error) { - caughtError = error; - } - - expect(caughtError).toBeUndefined(); - }); - - it("should still update a profile properly without providing args", async () => { - const configs = getTypeConfigurations(); - const oldSum = 55; - (ProfileIO.exists as any) = jest.fn(() => { - return true; // pretend the profile already exists - }); - ProfileIO.readProfileFile = jest.fn((fullFilePath: string, type: "string") => { - return {name: profileName, type: profileTypeOne, sum: oldSum}; - }); - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - const processSecurePropertiesSpy = jest.spyOn(manager as any, "processSecureProperties"); - const newSum = 66; - const profileName = "myprofile"; - const saveResult = await manager.update({ - name: profileName, type: profileTypeOne, - profile: {sum: newSum} - }); - testLogger.info("Update profile result: " + inspect(saveResult)); - expect(saveResult.profile.sum).toEqual(newSum); - // Should have only processed secure properties once - expect(processSecurePropertiesSpy).toHaveBeenCalledTimes(1); - }); - - it("should still fail profile validation on creation if no args are provided", async () => { - const configs = getTypeConfigurations(); - - (ProfileIO.exists as any) = jest.fn(() => { - return true; // pretend the profile already exists - }); - ProfileIO.writeProfile = jest.fn((fullFilePath: string, profile: IProfile) => { - writtenProfile = profile; - }); - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - const profileName = "myprofile"; - - try { - await manager.save({ - name: profileName, type: profileTypeOne, - profile: {}, - overwrite: true - }); - } catch (e) { - testLogger.warn("Got error as expected:" + inspect(e.stack, {depth: null, breakLength: 40})); - expect(e.message).toContain("content"); - } - }); - - it("should still fail profile validation on update if no args are provided", async () => { - const configs = getTypeConfigurations(); - - (ProfileIO.exists as any) = jest.fn(() => { - return true; // pretend the profile already exists - }); - ProfileIO.writeProfile = jest.fn((fullFilePath: string, profile: IProfile) => { - writtenProfile = profile; - }); - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - const profileName = "myprofile"; - - try { - await manager.update({ - name: profileName, type: profileTypeOne, - profile: {}, - overwrite: true - }); - } catch (e) { - expect(e.message).toContain("content"); - } - }); - - it("If we provide a non existent handler to create a profile from command line arguments, " + - "we should get a helpful error.", async () => { - const configs = getTypeConfigurations(); - (ProfileIO.exists as any) = jest.fn(() => { - return true; // pretend the profile already exists - }); - configs[0].createProfileFromArgumentsHandler = __dirname + "/profileHandlers/fakearooni"; - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - try { - await manager.save({ - name: "badprofile", type: profileTypeOne, - profile: {sum: 2}, - args: {_: [], $0: "test", doesNotMatter: "hi"}, - overwrite: true - }); - } catch (e) { - testLogger.info("Received error as expected: " + inspect(e)); - expect(e.message).toContain("handler"); - expect(e.message.toLowerCase()).toContain("error"); - } - }); - - it("If we provide a non existent handler to update a profile from command line arguments, " + - "we should get a helpful error.", async () => { - const configs = getTypeConfigurations(); - (ProfileIO.exists as any) = jest.fn(() => { - return true; // pretend the profile already exists - }); - configs[0].updateProfileFromArgumentsHandler = __dirname + "/profileHandlers/fakearooni"; - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - try { - await manager.update({ - name: "badprofile", type: profileTypeOne, - profile: {sum: 2}, - args: {_: [], $0: "test", doesNotMatter: "hi"}, - overwrite: true - }); - } catch (e) { - testLogger.info("Received error as expected: " + inspect(e)); - expect(e.message).toContain("handler"); - expect(e.message.toLowerCase()).toContain("error"); - } - }); - - it("should catch errors thrown by custom profile create handler and expose them " + - "to the user", async () => { - const configs = getTypeConfigurations(); - - ProfileIO.writeProfile = jest.fn((fullFilePath: string, profile: IProfile) => { - // do nothing - }); - ProfileIO.readProfileFile = jest.fn((fullFilePath: string, type: "string") => { - return {name: profileName, type: profileTypeOne}; - }); - configs[0].createProfileFromArgumentsHandler = throwErrorHandler; - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - const a = 1; - const b = 2; - const profileName = "myprofile"; - try { - await manager.save({ - name: profileName, type: profileTypeOne, - profile: {}, - args: {_: [], $0: "test", a, b}, - overwrite: true - }); - } catch (e) { - testLogger.info("Received error as expected: " + inspect(e)); - expect(e.message).toContain("custom"); - expect(e.message).toContain("handler"); - expect(e.message).toContain("threw"); // expect the output from the error in the handler - } - - }); - it("should catch errors thrown by custom profile update handler and expose them " + - "to the user", async () => { - const configs = getTypeConfigurations(); - - ProfileIO.writeProfile = jest.fn((fullFilePath: string, profile: IProfile) => { - // do nothing - }); - ProfileIO.readProfileFile = jest.fn((fullFilePath: string, type: "string") => { - return {name: profileName, type: profileTypeOne}; - }); - configs[0].updateProfileFromArgumentsHandler = throwErrorHandler; - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeOne, - logger: testLogger, - typeConfigurations: configs - }); - const a = 1; - const b = 2; - const profileName = "myprofile"; - try { - await manager.update({ - name: profileName, type: profileTypeOne, - profile: {}, - args: {_: [], $0: "test", a, b}, - overwrite: true - }); - } catch (e) { - testLogger.info("Received error as expected: " + inspect(e)); - expect(e.message).toContain("custom"); - expect(e.message).toContain("handler"); - expect(e.message).toContain("threw"); // expect the output from the error in the handler - } - - }); - it("should create a profile with dependencies if the proper command line arguments are provided", - async () => { - (ProfileIO.exists as any) = jest.fn(() => { - return true; // pretend the dependent profile already exists - }); - const configs = getTypeConfigurations(); - ProfileIO.writeProfile = jest.fn( - (fullFilePath: string, profile: IProfile) => { - // do nothing - }); - ProfileIO.readProfileFile = jest.fn( - (fullFilePath: string, type: "string") => { - return {name: profileName, type: profileTypeOne, sum: 55}; - }); - - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeTwo, - logger: testLogger, - typeConfigurations: configs - }); - const dependentProfileName = "myFirstProfile"; - const profileName = "myprofile"; - - const args: any = {_: [], $0: "test"}; - args[ProfileUtils.getProfileOption(profileTypeOne)] = dependentProfileName; - const saveResult = await manager.save({ - name: profileName, type: profileTypeTwo, - profile: {}, - args, - overwrite: true - }); - expect(saveResult.profile.dependencies[0].name).toEqual(dependentProfileName); - expect(saveResult.profile.dependencies[0].type).toEqual(profileTypeOne); - }); - - it("should be able to map option definitions back to differently named " + - "profile fields on update", async () => { - const configs = getTypeConfigurations(); - const oldSum = 55; - (ProfileIO.exists as any) = jest.fn(() => { - return true; // pretend the profile already exists - }); - ProfileIO.readProfileFile = jest.fn((fullFilePath: string, - type: "string") => { - return { - name: profileName, - type: profileTypeThree, - sum: oldSum - }; - }); - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeThree, - logger: testLogger, - typeConfigurations: configs - }); - - const profileName = "myprofile"; - const property1Value = 5; - const property2Value = "hello"; - const updateResult = await manager.update({ - name: profileName, type: profileTypeThree, - profile: {}, - args: { - _: [], $0: "test", - differentProperty1: property1Value, - differentProperty2: property2Value, - myGrandChild: "johnny" - } - }); - testLogger.info("Update profile result: " + inspect(updateResult, {depth: null})); - expect(updateResult.profile.property1).toEqual(property1Value); - expect(updateResult.profile.property2).toEqual(property2Value); - expect(updateResult.profile.hasChild.hasGrandChild.grandChild).toEqual("johnny"); - }); - - it("should be able to map option definitions back to differently named " + - "profile fields on creation", async () => { - const configs = getTypeConfigurations(); - const oldSum = 55; - (ProfileIO.exists as any) = jest.fn(() => { - return true; // pretend the profile already exists - }); - ProfileIO.readProfileFile = jest.fn((fullFilePath: string, - type: "string") => { - return { - name: profileName, - type: profileTypeThree, - sum: oldSum - }; - }); - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeThree, - logger: testLogger, - typeConfigurations: configs - }); - - const profileName = "myprofile"; - const property1Value = 5; - const property2Value = "hello"; - const saveResult = await manager.save({ - name: profileName, type: profileTypeThree, - profile: {}, - args: { - _: [], $0: "test", - differentProperty1: property1Value, - differentProperty2: property2Value, - myGrandChild: "johnny" - }, - overwrite: true - }); - testLogger.info("Save profile result: " + inspect(saveResult, {depth: null})); - expect(saveResult.profile.property1).toEqual(property1Value); - expect(saveResult.profile.property2).toEqual(property2Value); - expect(saveResult.profile.hasChild.hasGrandChild.grandChild).toEqual("johnny"); - }); - - - it("should provide a helpful error message if an error is encountered saving the profile " + - "while updating", async () => { - const configs = getTypeConfigurations(); - const oldSum = 55; - (ProfileIO.exists as any)= jest.fn(() => { - return true; // pretend the profile already exists - }); - ProfileIO.readProfileFile = jest.fn((fullFilePath: string, - type: "string") => { - return { - name: profileName, - type: profileTypeThree, - sum: oldSum - }; - }); - - const manager = new CliProfileManager({ - profileRootDirectory: profileDir, - type: profileTypeThree, - logger: testLogger, - typeConfigurations: configs - }); - const errMessage = "weasel"; - (CliProfileManager.prototype as any).saveProfile = jest.fn(async (parms: ISaveProfileFromCliArgs) => { - throw new ImperativeError({msg: errMessage}); - }); - const profileName = "myprofile"; - const property1Value = 5; - const property2Value = "hello"; - try { - await manager.update({ - name: profileName, type: profileTypeThree, - profile: {}, - args: { - _: [], $0: "test", - differentProperty1: property1Value, - differentProperty2: property2Value, - myGrandChild: "johnny" - } - }); - } catch (e) { - expect(e.message).toContain(errMessage); - expect(e.message).toContain("profile"); - return; - } - expect("should have encountered an error").toBeFalsy(); - }); - - it("should merge on update if \"merge\" is specified on the parms and no CLI args are specfied", async () => { - const prof = new CliProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: [{ - type: PROFILE_TYPE.STRAWBERRY, - schema: { - type: "object", - title: "test profile for updating on merging", - description: "ditto", - properties: { - myArrayVariable: { - type: "array" - }, - hasNestedArray: { - type: "object" - } - } - } - }], - type: PROFILE_TYPE.STRAWBERRY, - logger: testLogger - }); - const profileA = { - type: PROFILE_TYPE.STRAWBERRY, name: "first", - myArrayVariable: ["old_value1", "oldValue2"], - // test that the array replacement still works on deeply nested fields - hasNestedArray: {hasNestedArray: {hasNestedArray: ["old_value1", "old_value2"]}}, - }; - ProfileIO.writeProfile = jest.fn((path: string, profile: any) => { - // do nothing - }); - ProfileIO.exists = jest.fn((path: string) => { - return path.indexOf("meta") === -1 ? path : undefined; - }); - ProfileIO.readProfileFile = jest.fn((filePath: string, type: string) => { - if (type === PROFILE_TYPE.STRAWBERRY) { - return profileA; - } else { - return { - type: "apple", - name: "thing" - }; - } - }); - const profileB: IProfile = { - myArrayVariable: ["new_value1", "new_value2", "new_value3"], - hasNestedArray: {hasNestedArray: {hasNestedArray: ["new_value1", "new_value2", "new_value3", "new_value4"]}}, - }; - const updateResult = await prof.update({ - type: PROFILE_TYPE.STRAWBERRY, - name: "first", profile: profileB, merge: true - }); - const merged = updateResult.profile; - testLogger.info("Merged profile result: " + inspect(merged, {depth: null})); - expect(merged.myArrayVariable.length).toEqual(profileB.myArrayVariable.length); - for (const oldValue of profileA.myArrayVariable) { - expect(merged.myArrayVariable.indexOf(oldValue)).toEqual(-1); - } - - for (const oldValue of profileA.hasNestedArray.hasNestedArray.hasNestedArray) { - expect(merged.hasNestedArray.hasNestedArray.hasNestedArray.indexOf(oldValue)).toEqual(-1); - } - expect(merged.hasNestedArray.hasNestedArray.hasNestedArray.length).toEqual(profileB.hasNestedArray.hasNestedArray.hasNestedArray.length); - expect(merged.hasNestedArray).toEqual(profileB.hasNestedArray); - }); - - it("should merge on update if \"merge\" is specified on the parms and CLI args are specfied", async () => { - const prof = new CliProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: [{ - type: PROFILE_TYPE.STRAWBERRY, - schema: { - type: "object", - title: "test profile for updating on merging", - description: "ditto", - properties: { - myArrayVariable: { - type: "array", - optionDefinition: { - type: "array", - description: "my array variable", - name: "myArrayVariable" - } - }, - hasNestedArray: { - type: "object", - properties: { - hasNestedArray: { - type: "object", properties: { - hasNestedArray: { - type: "array", - optionDefinition: { - type: "array", - name: "hasNestedArray", - description: "nested array property" - } - } - } - } - } - } - } - } - }], - type: PROFILE_TYPE.STRAWBERRY, - logger: testLogger - }); - const profileA = { - myArrayVariable: ["old_value1", "oldValue2"], - // test that the array replacement still works on deeply nested fields - hasNestedArray: {hasNestedArray: {hasNestedArray: ["old_value1", "old_value2"]}}, - }; - ProfileIO.writeProfile = jest.fn((path: string, profile: any) => { - // do nothing - }); - ProfileIO.exists = jest.fn((path: string) => { - return path.indexOf("meta") === -1 ? path : undefined; - }); - ProfileIO.readProfileFile = jest.fn((filePath: string, type: string) => { - if (type === PROFILE_TYPE.STRAWBERRY) { - return profileA; - } else { - return { - type: "apple", - name: "thing" - }; - } - }); - const profileB: IProfile = { - type: PROFILE_TYPE.STRAWBERRY, - name: "first" - }; - const newArrayVariable = ["new_value1", "new_value2", "new_value3"]; - const newNestedArray = ["new_value1", "new_value2", "new_value3", "new_value4"]; - const updateResult = await prof.update({ - type: PROFILE_TYPE.STRAWBERRY, name: "first", - profile: profileB, args: { - $0: "dummy", _: [], - hasNestedArray: newNestedArray, - myArrayVariable: newArrayVariable, - }, - merge: true - }); - const merged = updateResult.profile; - testLogger.info("Merged profile result: " + inspect(merged, {depth: null})); - expect(merged.myArrayVariable.length).toEqual(newArrayVariable.length); - for (const oldValue of profileA.myArrayVariable) { - expect(merged.myArrayVariable.indexOf(oldValue)).toEqual(-1); - } - - for (const oldValue of profileA.hasNestedArray.hasNestedArray.hasNestedArray) { - expect(merged.hasNestedArray.hasNestedArray.hasNestedArray.indexOf(oldValue)).toEqual(-1); - } - expect(merged.hasNestedArray.hasNestedArray.hasNestedArray.length).toEqual(newNestedArray.length); - expect(merged.hasNestedArray.hasNestedArray.hasNestedArray).toEqual(newNestedArray); - }); -}); diff --git a/packages/imperative/src/cmd/__tests__/profiles/CommandProfileLoader.unit.test.ts b/packages/imperative/src/cmd/__tests__/profiles/CommandProfileLoader.unit.test.ts deleted file mode 100644 index 339040e297..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/CommandProfileLoader.unit.test.ts +++ /dev/null @@ -1,608 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -jest.mock("../../../profiles/src/BasicProfileManager"); -jest.mock("../../../profiles/src/BasicProfileManagerFactory"); -jest.mock("../../../utilities/src/ImperativeConfig"); -jest.mock("../../../logger/src/LoggerUtils"); -import { CommandProfileLoader } from "../../src/profiles/CommandProfileLoader"; -import { ICommandDefinition } from "../../src/doc/ICommandDefinition"; -import { BasicProfileManager } from "../../../profiles/src/BasicProfileManager"; -import { TestLogger } from "../../../../__tests__/src/TestLogger"; -import { CommandProfiles } from "../../src/profiles/CommandProfiles"; -import { ImperativeError } from "../../../error"; -import { BasicProfileManagerFactory, IProfile, IProfileLoaded } from "../../../profiles"; -import { ImperativeConfig } from "../../../utilities"; - -const TEST_PROFILES_DIR = "/test/data/profiles/fake"; - -const PROFILE_BANANA_TYPE: string = "banana"; -const STRAWBERRY_PROFILE_TYPE: string = "strawberry"; - -const SAMPLE_COMMAND_NO_PROFILE: ICommandDefinition = { - name: PROFILE_BANANA_TYPE, - description: "The banana command", - type: "command" -}; - -const SAMPLE_COMMAND_PROFILE: ICommandDefinition = { - name: PROFILE_BANANA_TYPE, - description: "The banana command", - type: "command", - profile: { - required: [PROFILE_BANANA_TYPE] - } -}; - -const SAMPLE_COMMAND_TWO_PROFILE_TYPES: ICommandDefinition = { - name: "bunch", - description: "The banana command", - type: "command", - profile: { - required: [PROFILE_BANANA_TYPE, STRAWBERRY_PROFILE_TYPE] - } -}; - -const SAMPLE_COMMAND_TWO_PROFILE_TYPES_ONE_OPTIONAL: ICommandDefinition = { - name: "bunch", - description: "The banana command", - type: "command", - profile: { - required: [PROFILE_BANANA_TYPE], - optional: [STRAWBERRY_PROFILE_TYPE] - } -}; - -const sampleRoot = __dirname + "/__tests__/__results__/data/"; - -describe("Command Profile Loader", () => { - - it("should allow us to create an instance", () => { - const loader = CommandProfileLoader.loader({ - commandDefinition: SAMPLE_COMMAND_NO_PROFILE, - profileManagerFactory: new BasicProfileManagerFactory(TEST_PROFILES_DIR), - logger: TestLogger.getTestLogger() - }); - expect(loader).toBeDefined(); - }); - - it("should allow us to create an instance and load nothing", async () => { - const loaded: CommandProfiles = await CommandProfileLoader.loader({ - commandDefinition: SAMPLE_COMMAND_NO_PROFILE, - profileManagerFactory: new BasicProfileManagerFactory(TEST_PROFILES_DIR), - logger: TestLogger.getTestLogger() - }).loadProfiles({ _: undefined as any, $0: undefined as any }); - expect(loaded).toBeDefined(); - }); - - it("should allow us to create an instance without a logger", () => { - const loader = CommandProfileLoader.loader({ - commandDefinition: SAMPLE_COMMAND_NO_PROFILE, - profileManagerFactory: new BasicProfileManagerFactory(TEST_PROFILES_DIR) - }); - expect(loader).toBeDefined(); - }); - - it("should allow us to create an instance (directly with constructor)", () => { - const loader = new CommandProfileLoader(SAMPLE_COMMAND_NO_PROFILE, - new BasicProfileManagerFactory(TEST_PROFILES_DIR)); - expect(loader).toBeDefined(); - }); - - it("should detect a bad logger instance", () => { - let error; - try { - const manager = new BasicProfileManagerFactory(TEST_PROFILES_DIR); - let logger: any = TestLogger.getTestLogger(); - logger = {bad: "logger"}; - CommandProfileLoader.loader({ - commandDefinition: SAMPLE_COMMAND_NO_PROFILE, - profileManagerFactory: manager, - logger - }); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect missing command definitions when creating the loader", () => { - let error; - try { - const manager = new BasicProfileManagerFactory(TEST_PROFILES_DIR); - CommandProfileLoader.loader({ - commandDefinition: undefined as any, - profileManagerFactory: manager, - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect missing profile manager when creating the loader", () => { - let error; - try { - const manager = new BasicProfileManagerFactory(TEST_PROFILES_DIR); - CommandProfileLoader.loader({ - commandDefinition: SAMPLE_COMMAND_NO_PROFILE, - profileManagerFactory: undefined as any, - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should not load old profiles when in team-config mode", async () => { - const manager = new BasicProfileManagerFactory(TEST_PROFILES_DIR); - const profManager = new BasicProfileManager({ - logger: TestLogger.getTestLogger(), - profileRootDirectory: sampleRoot, - type: PROFILE_BANANA_TYPE - }); - manager.getManager = jest.fn((type) => { - return profManager; - }); - profManager.load = jest.fn((parms) => Promise.resolve({ - message: "Profile Loaded", - type: PROFILE_BANANA_TYPE, - name: "tasty", - failNotFound: true, - profile: { - name: "tasty", - type: PROFILE_BANANA_TYPE, - } - })); - - // pretend that we have a team config - ImperativeConfig.instance.config = { - exists: true - } as any; - - const emptyProfileMap: Map = new Map(); - const emptyProfileMetaMap: Map = new Map(); - const noProfilesLoaded = new CommandProfiles(emptyProfileMap, emptyProfileMetaMap); - - // because we have a team config, we should load no old-scemptyProfileMaphool profiles - const loadedCmdProfiles: CommandProfiles = await CommandProfileLoader.loader({ - commandDefinition: SAMPLE_COMMAND_PROFILE, - profileManagerFactory: manager, - logger: TestLogger.getTestLogger() - }).loadProfiles({ _: undefined as any, $0: undefined as any }); - - expect(loadedCmdProfiles).toEqual(noProfilesLoaded); - - // restore to not having a team config for future tests - ImperativeConfig.instance.config = { - exists: false - } as any; - }); - - it("should allow us to load a required profile", async () => { - const manager = new BasicProfileManagerFactory(TEST_PROFILES_DIR); - const profManager = new BasicProfileManager({ - logger: TestLogger.getTestLogger(), - profileRootDirectory: sampleRoot, - type: PROFILE_BANANA_TYPE - }); - manager.getManager = jest.fn((type) => { - return profManager; - }); - profManager.load = jest.fn((parms) => Promise.resolve({ - message: "Profile Loaded", - type: PROFILE_BANANA_TYPE, - name: "tasty", - failNotFound: true, - profile: { - name: "tasty", - type: PROFILE_BANANA_TYPE, - } - })); - const response = await CommandProfileLoader.loader({ - commandDefinition: SAMPLE_COMMAND_PROFILE, - profileManagerFactory: manager, - logger: TestLogger.getTestLogger() - }) - .loadProfiles({ _: undefined as any, $0: undefined as any }); - // eslint-disable-next-line deprecation/deprecation - expect(response.get(PROFILE_BANANA_TYPE)).toMatchSnapshot(); - }); - - it("should percolate the load error to the caller", async () => { - const manager = new BasicProfileManagerFactory(TEST_PROFILES_DIR); - const profManager = new BasicProfileManager({ - logger: TestLogger.getTestLogger(), - profileRootDirectory: sampleRoot, - type: PROFILE_BANANA_TYPE - }); - manager.getManager = jest.fn((type) => { - return profManager; - }); - profManager.load = jest.fn((parms) => { - throw new ImperativeError({msg: `An error occurred during the load.`}); - }); - let error; - try { - const response = await CommandProfileLoader.loader({ - commandDefinition: SAMPLE_COMMAND_PROFILE, - profileManagerFactory: manager, - logger: TestLogger.getTestLogger() - }) - .loadProfiles({ _: undefined as any, $0: undefined as any }); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should react properly if the profile manager does not return an expected result for default", async () => { - const manager = new BasicProfileManagerFactory(TEST_PROFILES_DIR); - const profManager = new BasicProfileManager({ - logger: TestLogger.getTestLogger(), - profileRootDirectory: sampleRoot, - type: PROFILE_BANANA_TYPE - }); - manager.getManager = jest.fn((type) => { - return profManager; - }); - profManager.load = jest.fn((parms) => Promise.resolve({} as any )); - let error; - try { - const response = await CommandProfileLoader.loader({ - commandDefinition: SAMPLE_COMMAND_PROFILE, - profileManagerFactory: manager, - logger: TestLogger.getTestLogger() - }) - .loadProfiles({ _: undefined as any, $0: undefined as any }); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should react properly if the profile manager does not return an expected result", async () => { - const manager = new BasicProfileManagerFactory(TEST_PROFILES_DIR); - const profManager = new BasicProfileManager({ - logger: TestLogger.getTestLogger(), - profileRootDirectory: sampleRoot, - type: PROFILE_BANANA_TYPE - }); - manager.getManager = jest.fn((type) => { - return profManager; - }); - profManager.load = jest.fn((parms) => Promise.resolve({} as any)); - let error; - try { - const response = await CommandProfileLoader.loader({ - commandDefinition: SAMPLE_COMMAND_PROFILE, - profileManagerFactory: manager, - logger: TestLogger.getTestLogger() - }) - .loadProfiles({ "_": undefined as any, "$0": undefined as any, "banana-profile": "tasty"}); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should allow us to load a required profile by name", async () => { - const manager = new BasicProfileManagerFactory(TEST_PROFILES_DIR); - const profManager = new BasicProfileManager({ - logger: TestLogger.getTestLogger(), - profileRootDirectory: sampleRoot, - type: PROFILE_BANANA_TYPE - }); - manager.getManager = jest.fn((type) => { - return profManager; - }); - profManager.load = jest.fn((parms) => Promise.resolve({ - message: "Profile Loaded", - type: PROFILE_BANANA_TYPE, - name: "tasty", - failNotFound: true, - profile: { - name: "tasty", - type: PROFILE_BANANA_TYPE, - } - })); - const response = await CommandProfileLoader.loader({ - commandDefinition: SAMPLE_COMMAND_PROFILE, - profileManagerFactory: manager, - logger: TestLogger.getTestLogger() - }) - .loadProfiles({"_": undefined as any, "$0": undefined as any, "banana-profile": "tasty"}); - // eslint-disable-next-line deprecation/deprecation - expect(response.get(PROFILE_BANANA_TYPE)).toMatchSnapshot(); - }); - - it("should allow us to load a required profile by name with a dependency", async () => { - const manager = new BasicProfileManagerFactory(TEST_PROFILES_DIR); - const profManager = new BasicProfileManager({ - logger: TestLogger.getTestLogger(), - profileRootDirectory: sampleRoot, - type: PROFILE_BANANA_TYPE - }); - manager.getManager = jest.fn((type) => { - return profManager; - }); - profManager.load = jest.fn((parms) => Promise.resolve({ - message: "Profile Loaded", - type: PROFILE_BANANA_TYPE, - name: "tasty", - failNotFound: true, - profile: { - name: "tasty", - type: PROFILE_BANANA_TYPE, - }, - dependenciesLoaded: true, - dependencyLoadResponses: [ - { - message: "Profile Loaded", - type: STRAWBERRY_PROFILE_TYPE, - name: "tasty", - failNotFound: true, - profile: { - name: "red", - type: STRAWBERRY_PROFILE_TYPE, - }, - } - ] - })); - const response = await CommandProfileLoader.loader({ - commandDefinition: SAMPLE_COMMAND_PROFILE, - profileManagerFactory: manager, - logger: TestLogger.getTestLogger() - }) - .loadProfiles({"_": undefined as any, "$0": undefined as any, "banana-profile": "tasty"}); - // eslint-disable-next-line deprecation/deprecation - expect(response.get(PROFILE_BANANA_TYPE)).toMatchSnapshot(); - // eslint-disable-next-line deprecation/deprecation - expect(response.get(STRAWBERRY_PROFILE_TYPE)).toMatchSnapshot(); - }); - - it("should allow us to load two different required types", async () => { - const manager = new BasicProfileManagerFactory(TEST_PROFILES_DIR); - const profManagerBanana = new BasicProfileManager({ - logger: TestLogger.getTestLogger(), - profileRootDirectory: sampleRoot, - type: PROFILE_BANANA_TYPE - }); - const profManagerStrawberry = new BasicProfileManager({ - logger: TestLogger.getTestLogger(), - profileRootDirectory: sampleRoot, - type: PROFILE_BANANA_TYPE - }); - manager.getManager = jest.fn((type) => { - if (type === PROFILE_BANANA_TYPE) { - return profManagerBanana; - } - if (type === STRAWBERRY_PROFILE_TYPE) { - return profManagerStrawberry; - } - return undefined as any; - }); - profManagerBanana.load = jest.fn((parms) => Promise.resolve({ - message: "Profile Loaded", - type: PROFILE_BANANA_TYPE, - name: "tasty", - failNotFound: true, - profile: { - name: "tasty", - type: PROFILE_BANANA_TYPE, - } - })); - profManagerStrawberry.load = jest.fn((parms) => Promise.resolve({ - message: "Profile Loaded", - type: STRAWBERRY_PROFILE_TYPE, - name: "tasty", - failNotFound: true, - profile: { - name: "red", - type: STRAWBERRY_PROFILE_TYPE, - } - })); - const response = await CommandProfileLoader.loader({ - commandDefinition: SAMPLE_COMMAND_TWO_PROFILE_TYPES, - profileManagerFactory: manager, - logger: TestLogger.getTestLogger() - }) - .loadProfiles({"_": undefined as any, "$0": undefined as any, "banana-profile": "tasty", "strawberry-profile": "red"}); - // eslint-disable-next-line deprecation/deprecation - expect(response.get(PROFILE_BANANA_TYPE)).toMatchSnapshot(); - // eslint-disable-next-line deprecation/deprecation - expect(response.get(STRAWBERRY_PROFILE_TYPE)).toMatchSnapshot(); - }); - - it("should percolate the error if a required profile for one type is not found", async () => { - const manager = new BasicProfileManagerFactory(TEST_PROFILES_DIR); - const profManagerBanana = new BasicProfileManager({ - logger: TestLogger.getTestLogger(), - profileRootDirectory: sampleRoot, - type: PROFILE_BANANA_TYPE - }); - const profManagerStrawberry = new BasicProfileManager({ - logger: TestLogger.getTestLogger(), - profileRootDirectory: sampleRoot, - type: PROFILE_BANANA_TYPE - }); - manager.getManager = jest.fn((type) => { - if (type === PROFILE_BANANA_TYPE) { - return profManagerBanana; - } - if (type === STRAWBERRY_PROFILE_TYPE) { - return profManagerStrawberry; - } - return undefined as any; - }); - profManagerBanana.load = jest.fn((parms) => Promise.resolve({ - message: "Profile Loaded", - type: PROFILE_BANANA_TYPE, - name: "tasty", - failNotFound: true, - profile: { - name: "tasty", - type: PROFILE_BANANA_TYPE, - } - })); - profManagerStrawberry.load = jest.fn((parms) => { - throw new ImperativeError({msg: `Not found`}); - }); - let error; - try { - const response = await CommandProfileLoader.loader({ - commandDefinition: SAMPLE_COMMAND_TWO_PROFILE_TYPES, - profileManagerFactory: manager, - logger: TestLogger.getTestLogger() - }) - .loadProfiles({"_": undefined as any, "$0": undefined as any, "banana-profile": "tasty", "strawberry-profile": "red"}); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should handle multiple loads of the same type", async () => { - const manager = new BasicProfileManagerFactory(TEST_PROFILES_DIR); - const profManagerBanana = new BasicProfileManager({ - logger: TestLogger.getTestLogger(), - profileRootDirectory: sampleRoot, - type: PROFILE_BANANA_TYPE - }); - manager.getManager = jest.fn((type) => { - if (type === PROFILE_BANANA_TYPE) { - return profManagerBanana; - } - return undefined as any; - }); - profManagerBanana.load = jest.fn((parms) => Promise.resolve({ - message: "Profile Loaded", - type: PROFILE_BANANA_TYPE, - name: "tasty", - failNotFound: true, - profile: { - name: "tasty", - type: PROFILE_BANANA_TYPE, - }, - dependenciesLoaded: true, - dependencyLoadResponses: [ - { - message: "Profile Loaded", - type: PROFILE_BANANA_TYPE, - name: "great", - failNotFound: true, - profile: { - name: "great", - type: PROFILE_BANANA_TYPE, - }, - dependenciesLoaded: true, - dependencyLoadResponses: [ - { - message: "Profile Loaded", - type: PROFILE_BANANA_TYPE, - name: "awesome", - failNotFound: true, - profile: { - name: "awesome", - type: PROFILE_BANANA_TYPE, - }, - } - ] - } - ] - })); - // commandDefinition: SAMPLE_COMMAND_TWO_PROFILE_TYPES_ONE_OPTIONAL, - const response = await CommandProfileLoader.loader({ - commandDefinition: SAMPLE_COMMAND_PROFILE, - profileManagerFactory: manager, logger: - TestLogger.getTestLogger() - }).loadProfiles({"_": undefined as any, "$0": undefined as any, "banana-profile": "tasty"}); - // eslint-disable-next-line deprecation/deprecation - expect(response.getAll(PROFILE_BANANA_TYPE)[0]).toMatchSnapshot(); - // eslint-disable-next-line deprecation/deprecation - expect(response.getAll(PROFILE_BANANA_TYPE)[1]).toMatchSnapshot(); - // eslint-disable-next-line deprecation/deprecation - expect(response.getAll(PROFILE_BANANA_TYPE)[2]).toMatchSnapshot(); - // eslint-disable-next-line deprecation/deprecation - expect(response.get(PROFILE_BANANA_TYPE)).toMatchSnapshot(); - // eslint-disable-next-line deprecation/deprecation - expect(response.getAll(PROFILE_BANANA_TYPE)).toMatchSnapshot(); - }); - - it("should handle load of required and optional profiles", async () => { - const manager = new BasicProfileManagerFactory(TEST_PROFILES_DIR); - const profManagerBanana = new BasicProfileManager({ - logger: TestLogger.getTestLogger(), - profileRootDirectory: sampleRoot, - type: PROFILE_BANANA_TYPE - }); - const profManagerStrawberry = new BasicProfileManager({ - logger: TestLogger.getTestLogger(), - profileRootDirectory: sampleRoot, - type: STRAWBERRY_PROFILE_TYPE - }); - manager.getManager = jest.fn((type) => { - if (type === PROFILE_BANANA_TYPE) { - return profManagerBanana; - } - if (type === STRAWBERRY_PROFILE_TYPE) { - return profManagerStrawberry; - } - return undefined as any; - }); - profManagerBanana.load = jest.fn((parms) => Promise.resolve({ - message: "Profile Loaded", - type: PROFILE_BANANA_TYPE, - name: "tasty", - failNotFound: true, - profile: { - name: "tasty", - type: PROFILE_BANANA_TYPE, - } - })); - profManagerStrawberry.load = jest.fn((parms) => Promise.resolve({ - message: "Profile Loaded", - type: STRAWBERRY_PROFILE_TYPE, - name: "tasty", - failNotFound: true, - profile: { - name: "red", - type: STRAWBERRY_PROFILE_TYPE, - } - })); - - const response = await CommandProfileLoader.loader({ - commandDefinition: SAMPLE_COMMAND_TWO_PROFILE_TYPES_ONE_OPTIONAL, - profileManagerFactory: manager, logger: - TestLogger.getTestLogger() - }).loadProfiles({"_": undefined as any, "$0": undefined as any, "banana-profile": "tasty", "strawberry-profile": "red"}); - // eslint-disable-next-line deprecation/deprecation - expect(response.get(PROFILE_BANANA_TYPE)).toMatchSnapshot(); - // eslint-disable-next-line deprecation/deprecation - expect(response.get(STRAWBERRY_PROFILE_TYPE)).toMatchSnapshot(); - }); -}); diff --git a/packages/imperative/src/cmd/__tests__/profiles/CommandProfiles.unit.test.ts b/packages/imperative/src/cmd/__tests__/profiles/CommandProfiles.unit.test.ts deleted file mode 100644 index 6b681bc2fd..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/CommandProfiles.unit.test.ts +++ /dev/null @@ -1,253 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IProfile, IProfileLoaded } from "../../../profiles"; -import { CommandProfiles } from "../../src/profiles/CommandProfiles"; -import { ImperativeError } from "../../../error"; - -const BANANA_PROFILE_TYPE: string = "banana"; -const STRAWBERRY_PROFILE_TYPE: string = "strawberry"; - -describe("Command Profiles", () => { - it("should should allow us to create an instance", () => { - let caughtError; - try { - const profiles = new CommandProfiles(new Map()); - } catch (error) { - caughtError = error; - } - expect(caughtError).toBeUndefined(); - }); - - it("should detect missing parameters", () => { - let error; - try { - const profiles = new CommandProfiles(undefined); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect that the parameters are not a map", () => { - let error; - try { - const map = { not: "a-map" }; - new CommandProfiles(map as any); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should accept a profile map and allow us to retrieve them", () => { - const map = new Map(); - map.set(BANANA_PROFILE_TYPE, [{ - name: "tasty", - type: BANANA_PROFILE_TYPE, - age: 1 - }]); - map.set(STRAWBERRY_PROFILE_TYPE, [{ - name: "great", - type: STRAWBERRY_PROFILE_TYPE, - age: 1 - }, { - name: "awesome", - type: STRAWBERRY_PROFILE_TYPE, - age: 2 - }]); - const profiles = new CommandProfiles(map); - // eslint-disable-next-line deprecation/deprecation - expect(profiles.getAll(BANANA_PROFILE_TYPE)).toMatchSnapshot(); - // eslint-disable-next-line deprecation/deprecation - expect(profiles.getAll(STRAWBERRY_PROFILE_TYPE)).toMatchSnapshot(); - // eslint-disable-next-line deprecation/deprecation - expect(profiles.get(STRAWBERRY_PROFILE_TYPE)).toMatchSnapshot(); - // eslint-disable-next-line deprecation/deprecation - expect(profiles.get(BANANA_PROFILE_TYPE)).toMatchSnapshot(); - }); - - it("should throw an error if get does not have the profile type in the map", () => { - const map = new Map(); - map.set(BANANA_PROFILE_TYPE, [{ - name: "tasty", - type: BANANA_PROFILE_TYPE, - age: 1 - }]); - let error; - try { - const profiles = new CommandProfiles(map); - // eslint-disable-next-line deprecation/deprecation - profiles.get(STRAWBERRY_PROFILE_TYPE); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - expect(error.additionalDetails).toMatchSnapshot(); - }); - - it("should not throw an error if get does not have the profile type but throw not found is false", () => { - const map = new Map(); - map.set(BANANA_PROFILE_TYPE, [{ - name: "tasty", - type: BANANA_PROFILE_TYPE, - age: 1 - }]); - let error; - let response; - try { - const profiles = new CommandProfiles(map); - // eslint-disable-next-line deprecation/deprecation - response = profiles.get(STRAWBERRY_PROFILE_TYPE, false); - } catch (e) { - error = e; - } - expect(error).toBeUndefined(); - expect(response).toBeUndefined(); - }); - - it("should accept a profile map and allow us to retrieve by name", () => { - const map = new Map(); - map.set(STRAWBERRY_PROFILE_TYPE, [{ - name: "great", - type: STRAWBERRY_PROFILE_TYPE, - age: 1 - }, { - name: "awesome", - type: STRAWBERRY_PROFILE_TYPE, - age: 2 - }]); - const profiles = new CommandProfiles(map); - // eslint-disable-next-line deprecation/deprecation - const awesome = profiles.get(STRAWBERRY_PROFILE_TYPE, true, "awesome"); - expect(awesome).toMatchSnapshot(); - }); - - it("should accept a loaded profile map and allow us to retrieve by name", () => { - const map = new Map(); - map.set(STRAWBERRY_PROFILE_TYPE, [{ - name: "great", - type: STRAWBERRY_PROFILE_TYPE, - age: 1 - }, { - name: "awesome", - type: STRAWBERRY_PROFILE_TYPE, - age: 2 - }]); - const metaMap = new Map(); - metaMap.set(STRAWBERRY_PROFILE_TYPE, [{ - name: "great", - type: STRAWBERRY_PROFILE_TYPE, - profile: { - age: 1 - }, - message: "just right", - failNotFound: false - }, - { - name: "gross", - type: STRAWBERRY_PROFILE_TYPE, - profile: { - age: 3 - }, - message: "too old", - failNotFound: false - }]); - const profiles = new CommandProfiles(map, metaMap); - // eslint-disable-next-line deprecation/deprecation - const awesome = profiles.getMeta(STRAWBERRY_PROFILE_TYPE, false, "great"); - expect(awesome).toMatchSnapshot(); - }); - - it("should accept a loaded profile map and allow us to retrieve without a name", () => { - const map = new Map(); - map.set(STRAWBERRY_PROFILE_TYPE, [{ - name: "great", - type: STRAWBERRY_PROFILE_TYPE, - age: 1 - }, { - name: "awesome", - type: STRAWBERRY_PROFILE_TYPE, - age: 2 - }]); - const metaMap = new Map(); - metaMap.set(STRAWBERRY_PROFILE_TYPE, [{ - name: "great", - type: STRAWBERRY_PROFILE_TYPE, - profile: { - age: 1 - }, - message: "just right", - failNotFound: false - }, - { - name: "gross", - type: STRAWBERRY_PROFILE_TYPE, - profile: { - age: 3 - }, - message: "too old", - failNotFound: false - }]); - const profiles = new CommandProfiles(map, metaMap); - // eslint-disable-next-line deprecation/deprecation - const awesome = profiles.getMeta(STRAWBERRY_PROFILE_TYPE, false, null); - expect(awesome).toMatchSnapshot(); - }); - - it("should accept a loaded profile map and allow us to retrieve with a name and fail", () => { - const map = new Map(); - map.set(STRAWBERRY_PROFILE_TYPE, [{ - name: "great", - type: STRAWBERRY_PROFILE_TYPE, - age: 1 - }, { - name: "awesome", - type: STRAWBERRY_PROFILE_TYPE, - age: 2 - }]); - const metaMap = new Map(); - metaMap.set(STRAWBERRY_PROFILE_TYPE, [{ - name: "great", - type: STRAWBERRY_PROFILE_TYPE, - profile: { - age: 1 - }, - message: "just right", - failNotFound: true - }, - { - name: "gross", - type: STRAWBERRY_PROFILE_TYPE, - profile: { - age: 3 - }, - message: "too old", - failNotFound: true - }]); - const profiles = new CommandProfiles(map, metaMap); - - let err; - try { - // eslint-disable-next-line deprecation/deprecation - const awesome = profiles.getMeta("unknown", true, "tasty"); - } catch (thrownError) { - err = thrownError; - } - expect(err.message).toMatchSnapshot(); - }); -}); diff --git a/packages/imperative/src/cmd/__tests__/profiles/__snapshots__/CliProfileManager.credentials.unit.test.ts.snap b/packages/imperative/src/cmd/__tests__/profiles/__snapshots__/CliProfileManager.credentials.unit.test.ts.snap deleted file mode 100644 index 812cc058da..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/__snapshots__/CliProfileManager.credentials.unit.test.ts.snap +++ /dev/null @@ -1,45 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Cli Profile Manager Credential Manager functionality Load operation should not attempt to load secure fields if no credential manager is present 1`] = ` -Object { - "name": "My-secure-orange", - "password": null, - "secureBox": Object { - "myCode": "managed by", - "myEmptyMiniBox": Object { - "emptyMe": null, - }, - "myFlag": "managed by", - "myMiniBox": Object { - "miniMe": null, - }, - "myPhone": "managed by", - "myPhrase": "managed by", - "mySet": "managed by", - }, - "type": "secure-orange", - "username": "username", -} -`; - -exports[`Cli Profile Manager Credential Manager functionality Load operation should not load credentials from a profile if noSecure is specified 1`] = ` -Object { - "name": "My-secure-orange", - "password": null, - "secureBox": Object { - "myCode": "managed by", - "myEmptyMiniBox": Object { - "emptyMe": null, - }, - "myFlag": "managed by", - "myMiniBox": Object { - "miniMe": null, - }, - "myPhone": "managed by", - "myPhrase": "managed by", - "mySet": "managed by", - }, - "type": "secure-orange", - "username": "username", -} -`; diff --git a/packages/imperative/src/cmd/__tests__/profiles/__snapshots__/CommandProfileLoader.unit.test.ts.snap b/packages/imperative/src/cmd/__tests__/profiles/__snapshots__/CommandProfileLoader.unit.test.ts.snap deleted file mode 100644 index f82bee987d..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/__snapshots__/CommandProfileLoader.unit.test.ts.snap +++ /dev/null @@ -1,116 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Command Profile Loader should allow us to load a required profile 1`] = ` -Object { - "name": "tasty", - "type": "banana", -} -`; - -exports[`Command Profile Loader should allow us to load a required profile by name 1`] = ` -Object { - "name": "tasty", - "type": "banana", -} -`; - -exports[`Command Profile Loader should allow us to load a required profile by name with a dependency 1`] = ` -Object { - "name": "tasty", - "type": "banana", -} -`; - -exports[`Command Profile Loader should allow us to load a required profile by name with a dependency 2`] = ` -Object { - "name": "red", - "type": "strawberry", -} -`; - -exports[`Command Profile Loader should allow us to load two different required types 1`] = ` -Object { - "name": "tasty", - "type": "banana", -} -`; - -exports[`Command Profile Loader should allow us to load two different required types 2`] = ` -Object { - "name": "red", - "type": "strawberry", -} -`; - -exports[`Command Profile Loader should detect a bad logger instance 1`] = `"Expect Error: Could not construct the profile loader. The \\"logger\\" supplied is not of type Logger."`; - -exports[`Command Profile Loader should detect missing command definitions when creating the loader 1`] = `"Expect Error: Could not construct the profile loader. No command definition supplied."`; - -exports[`Command Profile Loader should detect missing profile manager when creating the loader 1`] = `"Expect Error: Could not construct the profile loader. No profile factory supplied."`; - -exports[`Command Profile Loader should handle load of required and optional profiles 1`] = ` -Object { - "name": "tasty", - "type": "banana", -} -`; - -exports[`Command Profile Loader should handle load of required and optional profiles 2`] = ` -Object { - "name": "red", - "type": "strawberry", -} -`; - -exports[`Command Profile Loader should handle multiple loads of the same type 1`] = ` -Object { - "name": "tasty", - "type": "banana", -} -`; - -exports[`Command Profile Loader should handle multiple loads of the same type 2`] = ` -Object { - "name": "great", - "type": "banana", -} -`; - -exports[`Command Profile Loader should handle multiple loads of the same type 3`] = ` -Object { - "name": "awesome", - "type": "banana", -} -`; - -exports[`Command Profile Loader should handle multiple loads of the same type 4`] = ` -Object { - "name": "tasty", - "type": "banana", -} -`; - -exports[`Command Profile Loader should handle multiple loads of the same type 5`] = ` -Array [ - Object { - "name": "tasty", - "type": "banana", - }, - Object { - "name": "great", - "type": "banana", - }, - Object { - "name": "awesome", - "type": "banana", - }, -] -`; - -exports[`Command Profile Loader should percolate the error if a required profile for one type is not found 1`] = `"Not found"`; - -exports[`Command Profile Loader should percolate the load error to the caller 1`] = `"An error occurred during the load."`; - -exports[`Command Profile Loader should react properly if the profile manager does not return an expected result 1`] = `"Unexpected internal load error: The profile \\"tasty\\" was not loaded by the profile manager."`; - -exports[`Command Profile Loader should react properly if the profile manager does not return an expected result for default 1`] = `"Unexpected internal load error: The profile \\"default requested\\" was not loaded by the profile manager."`; diff --git a/packages/imperative/src/cmd/__tests__/profiles/__snapshots__/CommandProfiles.unit.test.ts.snap b/packages/imperative/src/cmd/__tests__/profiles/__snapshots__/CommandProfiles.unit.test.ts.snap deleted file mode 100644 index 7b5f0b59bb..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/__snapshots__/CommandProfiles.unit.test.ts.snap +++ /dev/null @@ -1,88 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Command Profiles should accept a loaded profile map and allow us to retrieve by name 1`] = ` -Object { - "failNotFound": false, - "message": "just right", - "name": "great", - "profile": Object { - "age": 1, - }, - "type": "strawberry", -} -`; - -exports[`Command Profiles should accept a loaded profile map and allow us to retrieve with a name and fail 1`] = `"Internal Error: No profiles of type \\"unknown\\" were loaded for this command."`; - -exports[`Command Profiles should accept a loaded profile map and allow us to retrieve without a name 1`] = ` -Object { - "failNotFound": false, - "message": "just right", - "name": "great", - "profile": Object { - "age": 1, - }, - "type": "strawberry", -} -`; - -exports[`Command Profiles should accept a profile map and allow us to retrieve by name 1`] = ` -Object { - "age": 2, - "name": "awesome", - "type": "strawberry", -} -`; - -exports[`Command Profiles should accept a profile map and allow us to retrieve them 1`] = ` -Array [ - Object { - "age": 1, - "name": "tasty", - "type": "banana", - }, -] -`; - -exports[`Command Profiles should accept a profile map and allow us to retrieve them 2`] = ` -Array [ - Object { - "age": 1, - "name": "great", - "type": "strawberry", - }, - Object { - "age": 2, - "name": "awesome", - "type": "strawberry", - }, -] -`; - -exports[`Command Profiles should accept a profile map and allow us to retrieve them 3`] = ` -Object { - "age": 1, - "name": "great", - "type": "strawberry", -} -`; - -exports[`Command Profiles should accept a profile map and allow us to retrieve them 4`] = ` -Object { - "age": 1, - "name": "tasty", - "type": "banana", -} -`; - -exports[`Command Profiles should detect missing parameters 1`] = `"Expect Error: Command Profiles Internal Error: No map was supplied."`; - -exports[`Command Profiles should detect that the parameters are not a map 1`] = `"Expect Error: Command Profiles Internal Error: The \\"map\\" supplied is not an instance of a map."`; - -exports[`Command Profiles should throw an error if get does not have the profile type in the map 1`] = `"Internal Error: No profiles of type \\"strawberry\\" were loaded for this command."`; - -exports[`Command Profiles should throw an error if get does not have the profile type in the map 2`] = ` -"This error can occur for one of two reasons: - - The \\"profile\\" property on the command definition document does NOT specify the requested profile type - - The profile type is marked \\"optional\\", no profiles of type \\"strawberry\\" have been created, and the command handler requested a profile of type \\"strawberry\\" with \\"failNotFound=true\\"" -`; diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/CompleteProfilesGroupBuilder.unit.test.ts b/packages/imperative/src/cmd/__tests__/profiles/builders/CompleteProfilesGroupBuilder.unit.test.ts deleted file mode 100644 index 04d7fe60e2..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/CompleteProfilesGroupBuilder.unit.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -jest.mock("../../../../utilities/src/ImperativeConfig"); - -import { ImperativeConfig } from "../../../../utilities"; -import { deleteHandlerPaths, testBuilderProfiles } from "./ProfileBuilderTestConstants"; -import { TestLogger } from "../../../../../__tests__/src/TestLogger"; -import { CompleteProfilesGroupBuilder } from "../../../../imperative/src/profiles/builders/CompleteProfilesGroupBuilder"; - -describe("Complete Profiles Group Builder", () => { - const logger = TestLogger.getTestLogger(); - - // pretend that we have a team config - (ImperativeConfig.instance.config as any) = { - exists: true, - formMainConfigPathNm: jest.fn(() => { - return "zowe.config.json"; - }) - }; - - it("should provide a valid command definition for the " + - "complete auto generated profile group if passed a valid " + - "profile configuration document", () => { - let commands = CompleteProfilesGroupBuilder.getProfileGroup(testBuilderProfiles, logger); - commands = deleteHandlerPaths(commands); - expect(commands).toMatchSnapshot(); - }); -}); diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/ProfileBuilderTestConstants.ts b/packages/imperative/src/cmd/__tests__/profiles/builders/ProfileBuilderTestConstants.ts deleted file mode 100644 index c282ed3626..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/ProfileBuilderTestConstants.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandDefinition } from "../../../src/doc/ICommandDefinition"; -import { ICommandProfileTypeConfiguration } from "../../../../cmd/src/doc/profiles/definition/ICommandProfileTypeConfiguration"; - -export const testBuilderProfiles: ICommandProfileTypeConfiguration[] = [ - { - type: "type-a", - schema: { - title: "Type A profile", - type: "object", - description: "Type A profile for builder tests", - properties: { - age: { - type: "number", - optionDefinition: { - name: "age", - type: "number", - description: "The age of the profile" - } - } - } - }, - validationPlanModule: "dummy" - }, - { - type: "type-b", - schema: { - title: "Type B profile", - type: "object", - description: "Type B profile for builder tests", - properties: { - age: { - type: "number", - optionDefinition: { - name: "legs", - type: "number", - description: "The number of legs" - } - } - } - } - } -]; - -/** - * Delete handlers from a command definition since the absolute path is different per - * machine - * @param {ICommandDefinition} command - the definition with the handlers removed - */ -export const deleteHandlerPaths = (command: ICommandDefinition) => { - command = JSON.parse(JSON.stringify(command)); // copy the command - delete command.handler; - const newChildren = []; - for (const child of command.children || []) { - newChildren.push(deleteHandlerPaths(child)); - } - command.children = newChildren; - return command; -}; diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesCreateCommandBuilder.unit.test.ts b/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesCreateCommandBuilder.unit.test.ts deleted file mode 100644 index 68c571efb2..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesCreateCommandBuilder.unit.test.ts +++ /dev/null @@ -1,117 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { deleteHandlerPaths, testBuilderProfiles } from "./ProfileBuilderTestConstants"; -import { TestLogger } from "../../../../../__tests__/src/TestLogger"; -import { ProfilesCreateCommandBuilder } from "../../../../imperative/src/profiles/builders/ProfilesCreateCommandBuilder"; - -describe("Profile Create Command Builder", () => { - const logger = TestLogger.getTestLogger(); - it("should provide a valid command definition for the " + - "profile create command based on our test profile type", () => { - const firstProfileType = testBuilderProfiles[0]; - let commands = new ProfilesCreateCommandBuilder(firstProfileType.type, logger, firstProfileType).buildFull(); - commands = deleteHandlerPaths(commands); - expect(commands).toMatchSnapshot(); - }); - - it("should expose options for nested properties", () => { - const command = new ProfilesCreateCommandBuilder("test", - logger, { - type: "test", - schema: { - title: "Type A profile", - type: "object", - description: "Type A profile for builder tests", - properties: { - myParent: { - type: "object", - properties: { - middleProperty: { - type: "object", - properties: { - myNestedProperty: { - optionDefinition: { - description: "The nested property", - type: "string", - name: "nested", - required: true - }, - type: "string" - } - } - } - } - }, - } - }, - validationPlanModule: "dummy" - }).buildFull(); - let nestedOptionFound = false; - for (const option of command.options) { - if (option.name === "nested") { - nestedOptionFound = true; - break; - } - } - expect(nestedOptionFound).toEqual(true); - }); - - it("should expose multiple options for nested properties", () => { - const command = new ProfilesCreateCommandBuilder("test", - logger, { - type: "test", - schema: { - title: "Type A profile", - type: "object", - description: "Type A profile for builder tests", - properties: { - myParent: { - type: "object", - properties: { - middleProperty: { - type: "object", - properties: { - myNestedProperty: { - optionDefinitions: [{ - description: "The first nested property", - type: "string", - name: "nested1", - required: true - }, { - description: "The second nested property", - type: "string", - name: "nested2", - required: true - }], - type: "string" - } - } - } - } - }, - } - }, - validationPlanModule: "dummy" - }).buildFull(); - let nestedOption1Found = false; - let nestedOption2Found = false; - for (const option of command.options) { - if (option.name === "nested1") { - nestedOption1Found = true; - } else if (option.name === "nested2") { - nestedOption2Found = true; - } - } - expect(nestedOption1Found).toEqual(true); - expect(nestedOption2Found).toEqual(true); - }); -}); diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesDeleteCommandBuilder.unit.test.ts b/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesDeleteCommandBuilder.unit.test.ts deleted file mode 100644 index 3586e80ed5..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesDeleteCommandBuilder.unit.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -jest.mock("../../../../utilities/src/ImperativeConfig"); - -import { deleteHandlerPaths, testBuilderProfiles } from "./ProfileBuilderTestConstants"; -import { TestLogger } from "../../../../../__tests__/src/TestLogger"; -import { ProfilesDeleteCommandBuilder } from "../../../../imperative/src/profiles/builders/ProfilesDeleteCommandBuilder"; -import { ImperativeConfig } from "../../../../utilities"; - -describe("Profile Delete Command Builder", () => { - const logger = TestLogger.getTestLogger(); - - // pretend that we have a team config - (ImperativeConfig.instance.config as any) = { - exists: true, - formMainConfigPathNm: jest.fn(() => { - return "zowe.config.json"; - }) - }; - - it("should provide a valid command definition for the " + - "profile delete command based on our test profile type", () => { - const firstProfileType = testBuilderProfiles[0]; - let commands = new ProfilesDeleteCommandBuilder(firstProfileType.type, logger, firstProfileType).buildFull(); - commands = deleteHandlerPaths(commands); - expect(commands).toMatchSnapshot(); - }); -}); diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesListCommandBuilder.unit.test.ts b/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesListCommandBuilder.unit.test.ts deleted file mode 100644 index 8b12c110ca..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesListCommandBuilder.unit.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { deleteHandlerPaths, testBuilderProfiles } from "./ProfileBuilderTestConstants"; -import { TestLogger } from "../../../../../__tests__/src/TestLogger"; -import { ProfilesListCommandBuilder } from "../../../../imperative/src/profiles/builders/ProfilesListCommandBuilder"; - - -describe("Profile List Command Builder", () => { - const logger = TestLogger.getTestLogger(); - it("should provide a valid command definition for the " + - "profile list command based on our test profile type", () => { - const firstProfileType = testBuilderProfiles[0]; - let commands = new ProfilesListCommandBuilder(firstProfileType.type, logger, firstProfileType).buildFull(); - commands = deleteHandlerPaths(commands); - expect(commands).toMatchSnapshot(); - }); -}); diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesSetCommandBuilder.unit.test.ts b/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesSetCommandBuilder.unit.test.ts deleted file mode 100644 index 4708f59ac6..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesSetCommandBuilder.unit.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { deleteHandlerPaths, testBuilderProfiles } from "./ProfileBuilderTestConstants"; -import { TestLogger } from "../../../../../__tests__/src/TestLogger"; -import { ProfilesSetCommandBuilder } from "../../../../imperative/src/profiles/builders/ProfilesSetCommandBuilder"; - -describe("Profile Set Command Builder", () => { - const logger = TestLogger.getTestLogger(); - it("should provide a valid command definition for the " + - "profile set command based on our test profile type", () => { - const firstProfileType = testBuilderProfiles[0]; - let commands = new ProfilesSetCommandBuilder(firstProfileType.type, logger, firstProfileType).buildFull(); - commands = deleteHandlerPaths(commands); - expect(commands).toMatchSnapshot(); - }); -}); diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesShowDependenciesCommandBuilder.unit.test.ts b/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesShowDependenciesCommandBuilder.unit.test.ts deleted file mode 100644 index d40c6aa50d..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesShowDependenciesCommandBuilder.unit.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { deleteHandlerPaths, testBuilderProfiles } from "./ProfileBuilderTestConstants"; -import { TestLogger } from "../../../../../__tests__/src/TestLogger"; -import { ProfilesShowDependenciesCommandBuilder } from "../../../../imperative/src/profiles/builders/ProfilesShowDependenciesCommandBuilder"; - -describe("Profile Show Dependencies Command Builder", () => { - const logger = TestLogger.getTestLogger(); - it("should provide a valid command definition for the " + - "profile show dependencies command based on our test profile type", () => { - const firstProfileType = testBuilderProfiles[0]; - let commands = new ProfilesShowDependenciesCommandBuilder(firstProfileType.type, logger, firstProfileType).buildFull(); - commands = deleteHandlerPaths(commands); - expect(commands).toMatchSnapshot(); - }); -}); diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesUpdateCommandBuilder.unit.test.ts b/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesUpdateCommandBuilder.unit.test.ts deleted file mode 100644 index b914a10749..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesUpdateCommandBuilder.unit.test.ts +++ /dev/null @@ -1,117 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { deleteHandlerPaths, testBuilderProfiles } from "./ProfileBuilderTestConstants"; -import { TestLogger } from "../../../../../__tests__/src/TestLogger"; -import { ProfilesUpdateCommandBuilder } from "../../../../imperative/src/profiles/builders/ProfilesUpdateCommandBuilder"; - -describe("Profile Update Command Builder", () => { - const logger = TestLogger.getTestLogger(); - it("should provide a valid command definition for the " + - "profile update command based on our test profile type", () => { - const firstProfileType = testBuilderProfiles[0]; - let commands = new ProfilesUpdateCommandBuilder(firstProfileType.type, logger, firstProfileType).buildFull(); - commands = deleteHandlerPaths(commands); - expect(commands).toMatchSnapshot(); - }); - - it("should expose options for nested properties", () => { - const command = new ProfilesUpdateCommandBuilder("test", - logger, { - type: "test", - schema: { - title: "Type A profile", - type: "object", - description: "Type A profile for builder tests", - properties: { - myParent: { - type: "object", - properties: { - middleProperty: { - type: "object", - properties: { - myNestedProperty: { - optionDefinition: { - description: "The nested property", - type: "string", - name: "nested", - required: true - }, - type: "string" - } - } - } - } - }, - } - }, - validationPlanModule: "dummy" - }).buildFull(); - let nestedOptionFound = false; - for (const option of command.options) { - if (option.name === "nested") { - nestedOptionFound = true; - break; - } - } - expect(nestedOptionFound).toEqual(true); - }); - - it("should expose multiple options for nested properties", () => { - const command = new ProfilesUpdateCommandBuilder("test", - logger, { - type: "test", - schema: { - title: "Type A profile", - type: "object", - description: "Type A profile for builder tests", - properties: { - myParent: { - type: "object", - properties: { - middleProperty: { - type: "object", - properties: { - myNestedProperty: { - optionDefinitions: [{ - description: "The first nested property", - type: "string", - name: "nested1", - required: true - }, { - description: "The second nested property", - type: "string", - name: "nested2", - required: true - }], - type: "string" - } - } - } - } - }, - } - }, - validationPlanModule: "dummy" - }).buildFull(); - let nestedOption1Found = false; - let nestedOption2Found = false; - for (const option of command.options) { - if (option.name === "nested1") { - nestedOption1Found = true; - } else if (option.name === "nested2") { - nestedOption2Found = true; - } - } - expect(nestedOption1Found).toEqual(true); - expect(nestedOption2Found).toEqual(true); - }); -}); diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesValidateCommandBuilder.unit.test.ts b/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesValidateCommandBuilder.unit.test.ts deleted file mode 100644 index b0111b8003..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/ProfilesValidateCommandBuilder.unit.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -jest.mock("../../../../utilities/src/ImperativeConfig"); - -import { deleteHandlerPaths, testBuilderProfiles } from "./ProfileBuilderTestConstants"; -import { TestLogger } from "../../../../../__tests__/src/TestLogger"; -import { ProfilesValidateCommandBuilder } from "../../../../imperative/src/profiles/builders/ProfilesValidateCommandBuilder"; -import { ImperativeConfig } from "../../../../utilities"; - -describe("Profile Validate Command Builder", () => { - const logger = TestLogger.getTestLogger(); - - // pretend that we have a team config - (ImperativeConfig.instance.config as any) = { - exists: true, - formMainConfigPathNm: jest.fn(() => { - return "zowe.config.json"; - }) - }; - - it("should provide a valid command definition for the " + - "profile validate command based on our test profile type", () => { - const firstProfileType = testBuilderProfiles[0]; - let commands = new ProfilesValidateCommandBuilder(firstProfileType.type, logger, firstProfileType).buildFull(); - commands = deleteHandlerPaths(commands); - expect(commands).toMatchSnapshot(); - }); -}); diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/CompleteProfilesGroupBuilder.unit.test.ts.snap b/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/CompleteProfilesGroupBuilder.unit.test.ts.snap deleted file mode 100644 index f13b61ced9..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/CompleteProfilesGroupBuilder.unit.test.ts.snap +++ /dev/null @@ -1,480 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Complete Profiles Group Builder should provide a valid command definition for the complete auto generated profile group if passed a valid profile configuration document 1`] = ` -Object { - "children": Array [ - Object { - "aliases": Array [ - "cre", - ], - "children": Array [ - Object { - "aliases": Array [ - "type-a", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-a", - }, - "deprecatedReplacement": "The 'config init' command", - "description": "Type A profile for builder tests", - "name": "type-a-profile", - "options": Array [ - Object { - "description": "The age of the profile", - "name": "age", - "type": "number", - }, - Object { - "aliases": Array [ - "ow", - ], - "description": "Overwrite the type-a profile when a profile of the same name exists.", - "name": "overwrite", - "type": "boolean", - }, - Object { - "aliases": Array [ - "dd", - ], - "description": "Disable populating profile values of undefined properties with default values.", - "name": "disable-defaults", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "Specifies the name of the new type-a profile. You can load this profile by using the name on commands that support the \\"--type-a-profile\\" option.", - "name": "profileName", - "required": true, - "type": "string", - }, - ], - "summary": "Create a type-a profile", - "type": "command", - }, - Object { - "aliases": Array [ - "type-b", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-b", - }, - "deprecatedReplacement": "The 'config init' command", - "description": "Type B profile for builder tests", - "name": "type-b-profile", - "options": Array [ - Object { - "description": "The number of legs", - "name": "legs", - "type": "number", - }, - Object { - "aliases": Array [ - "ow", - ], - "description": "Overwrite the type-b profile when a profile of the same name exists.", - "name": "overwrite", - "type": "boolean", - }, - Object { - "aliases": Array [ - "dd", - ], - "description": "Disable populating profile values of undefined properties with default values.", - "name": "disable-defaults", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "Specifies the name of the new type-b profile. You can load this profile by using the name on commands that support the \\"--type-b-profile\\" option.", - "name": "profileName", - "required": true, - "type": "string", - }, - ], - "summary": "Create a type-b profile", - "type": "command", - }, - ], - "deprecatedReplacement": "The 'config init' command", - "description": "Create new configuration profiles.", - "name": "create", - "summary": "Create new configuration profiles", - "type": "group", - }, - Object { - "aliases": Array [ - "upd", - ], - "children": Array [ - Object { - "aliases": Array [ - "type-a", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-a", - }, - "deprecatedReplacement": "The 'config set' command", - "description": "Type A profile for builder tests", - "name": "type-a-profile", - "options": Array [ - Object { - "absenceImplications": null, - "description": "The age of the profile", - "implies": null, - "name": "age", - "required": false, - "type": "number", - }, - ], - "positionals": Array [ - Object { - "description": "Specifies the name of the new type-a profile. You can load this profile by using the name on commands that support the \\"--type-a-profile\\" option.", - "name": "profileName", - "required": true, - "type": "string", - }, - ], - "summary": "Update a type-a profile. You can update any property present within the profile configuration. The updated profile will be printed so that you can review the result of the updates.", - "type": "command", - }, - Object { - "aliases": Array [ - "type-b", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-b", - }, - "deprecatedReplacement": "The 'config set' command", - "description": "Type B profile for builder tests", - "name": "type-b-profile", - "options": Array [ - Object { - "absenceImplications": null, - "description": "The number of legs", - "implies": null, - "name": "legs", - "required": false, - "type": "number", - }, - ], - "positionals": Array [ - Object { - "description": "Specifies the name of the new type-b profile. You can load this profile by using the name on commands that support the \\"--type-b-profile\\" option.", - "name": "profileName", - "required": true, - "type": "string", - }, - ], - "summary": "Update a type-b profile. You can update any property present within the profile configuration. The updated profile will be printed so that you can review the result of the updates.", - "type": "command", - }, - ], - "deprecatedReplacement": "The 'config set' command", - "description": "Update a {{type}} profile. You can update any property present within the profile configuration. The updated profile will be printed so that you can review the result of the updates.", - "name": "update", - "summary": "Update existing profiles", - "type": "group", - }, - Object { - "aliases": Array [ - "rm", - ], - "children": Array [ - Object { - "aliases": Array [ - "type-a", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-a", - }, - "deprecatedReplacement": "Edit your Zowe V2 configuration - zowe.config.json", - "description": "Delete a type-a profile. You must specify a profile name to be deleted. To find a list of available profiles for deletion, issue the profiles list command. By default, you will be prompted to confirm the profile removal.", - "examples": Array [ - Object { - "description": "Delete a type-a profile named profilename", - "options": "profilename", - }, - ], - "name": "type-a-profile", - "options": Array [ - Object { - "aliases": Array [], - "description": "Force deletion of profile, and dependent profiles if specified. No prompt will be displayed before deletion occurs.", - "name": "force", - "required": false, - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "Specifies the name of the type-a profile to be deleted. You can also load this profile by using the name on commands that support the \\"--type-a-profile\\" option.", - "name": "profileName", - "required": true, - "type": "string", - }, - ], - "summary": "Delete a type-a profile.", - "type": "command", - }, - Object { - "aliases": Array [ - "type-b", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-b", - }, - "deprecatedReplacement": "Edit your Zowe V2 configuration - zowe.config.json", - "description": "Delete a type-b profile. You must specify a profile name to be deleted. To find a list of available profiles for deletion, issue the profiles list command. By default, you will be prompted to confirm the profile removal.", - "examples": Array [ - Object { - "description": "Delete a type-b profile named profilename", - "options": "profilename", - }, - ], - "name": "type-b-profile", - "options": Array [ - Object { - "aliases": Array [], - "description": "Force deletion of profile, and dependent profiles if specified. No prompt will be displayed before deletion occurs.", - "name": "force", - "required": false, - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "Specifies the name of the type-b profile to be deleted. You can also load this profile by using the name on commands that support the \\"--type-b-profile\\" option.", - "name": "profileName", - "required": true, - "type": "string", - }, - ], - "summary": "Delete a type-b profile.", - "type": "command", - }, - ], - "deprecatedReplacement": "Edit your Zowe V2 configuration zowe.config.json", - "description": "Delete existing profiles.", - "name": "delete", - "summary": "Delete existing profiles", - "type": "group", - }, - Object { - "aliases": Array [ - "ls", - ], - "children": Array [ - Object { - "aliases": Array [ - "type-a", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-a", - }, - "deprecatedReplacement": "The 'config list' command", - "description": "Type A profile for builder tests", - "examples": Array [ - Object { - "description": "List profiles of type type-a", - "options": "", - }, - Object { - "description": "List profiles of type type-a and display their contents", - "options": "--sc", - }, - ], - "name": "type-a-profiles", - "options": Array [ - Object { - "aliases": Array [ - "sc", - ], - "description": "List type-a profiles and their contents. All profile details will be printed as part of command output.", - "name": "show-contents", - "required": false, - "type": "boolean", - }, - ], - "summary": "List profiles of the type type-a.", - "type": "command", - }, - Object { - "aliases": Array [ - "type-b", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-b", - }, - "deprecatedReplacement": "The 'config list' command", - "description": "Type B profile for builder tests", - "examples": Array [ - Object { - "description": "List profiles of type type-b", - "options": "", - }, - Object { - "description": "List profiles of type type-b and display their contents", - "options": "--sc", - }, - ], - "name": "type-b-profiles", - "options": Array [ - Object { - "aliases": Array [ - "sc", - ], - "description": "List type-b profiles and their contents. All profile details will be printed as part of command output.", - "name": "show-contents", - "required": false, - "type": "boolean", - }, - ], - "summary": "List profiles of the type type-b.", - "type": "command", - }, - ], - "deprecatedReplacement": "The 'config list' command", - "description": "List profiles of the type {{type}}.", - "name": "list", - "summary": "List existing profiles", - "type": "group", - }, - Object { - "aliases": Array [ - "set", - ], - "children": Array [ - Object { - "aliases": Array [ - "type-a", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-a", - }, - "deprecatedReplacement": "The 'config set' command", - "description": "The type-a set default-profiles command allows you to set the default profiles for this command group. When a type-a command is issued and no profile override options are specified, the default profiles for the command group are automatically loaded for the command based on the commands profile requirements.", - "examples": Array [ - Object { - "description": "Set the default profile for type type-a to the profile named 'profilename'", - "options": "profilename", - }, - ], - "name": "type-a-profile", - "options": Array [], - "positionals": Array [ - Object { - "description": "Specify a - profile for default usage within the type-a group. When you issue commands within the type-a group without a profile specified as part of the command, the default will be loaded instead.", - "name": "profileName", - "required": true, - "type": "string", - }, - ], - "summary": "Set the default - profiles for the type-a group", - "type": "command", - }, - Object { - "aliases": Array [ - "type-b", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-b", - }, - "deprecatedReplacement": "The 'config set' command", - "description": "The type-b set default-profiles command allows you to set the default profiles for this command group. When a type-b command is issued and no profile override options are specified, the default profiles for the command group are automatically loaded for the command based on the commands profile requirements.", - "examples": Array [ - Object { - "description": "Set the default profile for type type-b to the profile named 'profilename'", - "options": "profilename", - }, - ], - "name": "type-b-profile", - "options": Array [], - "positionals": Array [ - Object { - "description": "Specify a - profile for default usage within the type-b group. When you issue commands within the type-b group without a profile specified as part of the command, the default will be loaded instead.", - "name": "profileName", - "required": true, - "type": "string", - }, - ], - "summary": "Set the default - profiles for the type-b group", - "type": "command", - }, - ], - "deprecatedReplacement": "The 'config set' command", - "description": "Set which profiles are loaded by default.", - "name": "set-default", - "summary": "Set which profiles are loaded by default", - "type": "group", - }, - Object { - "aliases": Array [ - "val", - ], - "children": Array [ - Object { - "aliases": Array [ - "type-a", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-a", - }, - "deprecatedReplacement": "Edit your Zowe V2 configuration - zowe.config.json", - "description": "Test the validity of a type-a profile.", - "name": "type-a-profile", - "options": Array [ - Object { - "aliases": Array [ - "plan", - "p", - ], - "description": "Instead of validating your profile, print out a table of the tasks used for validation. This will explain the different services and functionality that will be tested during profile validation.", - "name": "print-plan-only", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "Specifies the name of the type-a profile to be deleted. You can also load this profile by using the name on commands that support the \\"--type-a-profile\\" option.", - "name": "profileName", - "required": false, - "type": "string", - }, - ], - "summary": "Test the validity of a type-a profile.", - "type": "command", - }, - ], - "deprecatedReplacement": "Edit your Zowe V2 configuration zowe.config.json", - "description": "Test the validity of your profiles.", - "name": "validate", - "summary": "Test the validity of a profile", - "type": "group", - }, - ], - "deprecatedReplacement": "The 'config init' command", - "description": "Create and manage configuration profiles.", - "name": "profiles", - "type": "group", -} -`; diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesCreateCommandBuilder.unit.test.ts.snap b/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesCreateCommandBuilder.unit.test.ts.snap deleted file mode 100644 index ef4241d63f..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesCreateCommandBuilder.unit.test.ts.snap +++ /dev/null @@ -1,49 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Profile Create Command Builder should provide a valid command definition for the profile create command based on our test profile type 1`] = ` -Object { - "aliases": Array [ - "type-a", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-a", - }, - "deprecatedReplacement": "The 'config init' command", - "description": "Type A profile for builder tests", - "name": "type-a-profile", - "options": Array [ - Object { - "description": "The age of the profile", - "name": "age", - "type": "number", - }, - Object { - "aliases": Array [ - "ow", - ], - "description": "Overwrite the type-a profile when a profile of the same name exists.", - "name": "overwrite", - "type": "boolean", - }, - Object { - "aliases": Array [ - "dd", - ], - "description": "Disable populating profile values of undefined properties with default values.", - "name": "disable-defaults", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "Specifies the name of the new type-a profile. You can load this profile by using the name on commands that support the \\"--type-a-profile\\" option.", - "name": "profileName", - "required": true, - "type": "string", - }, - ], - "summary": "Create a type-a profile", - "type": "command", -} -`; diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesDeleteCommandBuilder.unit.test.ts.snap b/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesDeleteCommandBuilder.unit.test.ts.snap deleted file mode 100644 index 619beaade5..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesDeleteCommandBuilder.unit.test.ts.snap +++ /dev/null @@ -1,42 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Profile Delete Command Builder should provide a valid command definition for the profile delete command based on our test profile type 1`] = ` -Object { - "aliases": Array [ - "type-a", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-a", - }, - "deprecatedReplacement": "Edit your Zowe V2 configuration - zowe.config.json", - "description": "Delete a type-a profile. You must specify a profile name to be deleted. To find a list of available profiles for deletion, issue the profiles list command. By default, you will be prompted to confirm the profile removal.", - "examples": Array [ - Object { - "description": "Delete a type-a profile named profilename", - "options": "profilename", - }, - ], - "name": "type-a-profile", - "options": Array [ - Object { - "aliases": Array [], - "description": "Force deletion of profile, and dependent profiles if specified. No prompt will be displayed before deletion occurs.", - "name": "force", - "required": false, - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "Specifies the name of the type-a profile to be deleted. You can also load this profile by using the name on commands that support the \\"--type-a-profile\\" option.", - "name": "profileName", - "required": true, - "type": "string", - }, - ], - "summary": "Delete a type-a profile.", - "type": "command", -} -`; diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesListCommandBuilder.unit.test.ts.snap b/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesListCommandBuilder.unit.test.ts.snap deleted file mode 100644 index 8dc551b1eb..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesListCommandBuilder.unit.test.ts.snap +++ /dev/null @@ -1,39 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Profile List Command Builder should provide a valid command definition for the profile list command based on our test profile type 1`] = ` -Object { - "aliases": Array [ - "type-a", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-a", - }, - "deprecatedReplacement": "The 'config list' command", - "description": "Type A profile for builder tests", - "examples": Array [ - Object { - "description": "List profiles of type type-a", - "options": "", - }, - Object { - "description": "List profiles of type type-a and display their contents", - "options": "--sc", - }, - ], - "name": "type-a-profiles", - "options": Array [ - Object { - "aliases": Array [ - "sc", - ], - "description": "List type-a profiles and their contents. All profile details will be printed as part of command output.", - "name": "show-contents", - "required": false, - "type": "boolean", - }, - ], - "summary": "List profiles of the type type-a.", - "type": "command", -} -`; diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesSetCommandBuilder.unit.test.ts.snap b/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesSetCommandBuilder.unit.test.ts.snap deleted file mode 100644 index 912ca6b6cc..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesSetCommandBuilder.unit.test.ts.snap +++ /dev/null @@ -1,35 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Profile Set Command Builder should provide a valid command definition for the profile set command based on our test profile type 1`] = ` -Object { - "aliases": Array [ - "type-a", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-a", - }, - "deprecatedReplacement": "The 'config set' command", - "description": "The type-a set default-profiles command allows you to set the default profiles for this command group. When a type-a command is issued and no profile override options are specified, the default profiles for the command group are automatically loaded for the command based on the commands profile requirements.", - "examples": Array [ - Object { - "description": "Set the default profile for type type-a to the profile named 'profilename'", - "options": "profilename", - }, - ], - "name": "type-a-profile", - "options": Array [], - "positionals": Array [ - Object { - "description": "Specify a - profile for default usage within the type-a group. When you issue commands within the type-a group without a profile specified as part of the command, the default will be loaded instead.", - "name": "profileName", - "required": true, - "type": "string", - }, - ], - "summary": "Set the default - profiles for the type-a group", - "type": "command", -} -`; diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesShowDependenciesCommandBuilder.unit.test.ts.snap b/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesShowDependenciesCommandBuilder.unit.test.ts.snap deleted file mode 100644 index c43a6c28e8..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesShowDependenciesCommandBuilder.unit.test.ts.snap +++ /dev/null @@ -1,26 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Profile Show Dependencies Command Builder should provide a valid command definition for the profile show dependencies command based on our test profile type 1`] = ` -Object { - "aliases": Array [ - "type-a", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-a", - }, - "description": "Type A profile for builder tests", - "name": "type-a-profile", - "options": Array [], - "positionals": Array [ - Object { - "description": "Specifies the name of the type-a profile to be deleted. You can also load this profile by using the name on commands that support the \\"--type-a-profile\\" option.", - "name": "profileName", - "required": true, - "type": "string", - }, - ], - "summary": "View all profiles which may be used within a selected group.", - "type": "command", -} -`; diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesUpdateCommandBuilder.unit.test.ts.snap b/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesUpdateCommandBuilder.unit.test.ts.snap deleted file mode 100644 index d432d7c49e..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesUpdateCommandBuilder.unit.test.ts.snap +++ /dev/null @@ -1,36 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Profile Update Command Builder should provide a valid command definition for the profile update command based on our test profile type 1`] = ` -Object { - "aliases": Array [ - "type-a", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-a", - }, - "deprecatedReplacement": "The 'config set' command", - "description": "Type A profile for builder tests", - "name": "type-a-profile", - "options": Array [ - Object { - "absenceImplications": null, - "description": "The age of the profile", - "implies": null, - "name": "age", - "required": false, - "type": "number", - }, - ], - "positionals": Array [ - Object { - "description": "Specifies the name of the new type-a profile. You can load this profile by using the name on commands that support the \\"--type-a-profile\\" option.", - "name": "profileName", - "required": true, - "type": "string", - }, - ], - "summary": "Update a type-a profile. You can update any property present within the profile configuration. The updated profile will be printed so that you can review the result of the updates.", - "type": "command", -} -`; diff --git a/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesValidateCommandBuilder.unit.test.ts.snap b/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesValidateCommandBuilder.unit.test.ts.snap deleted file mode 100644 index d40611823b..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/builders/__snapshots__/ProfilesValidateCommandBuilder.unit.test.ts.snap +++ /dev/null @@ -1,38 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Profile Validate Command Builder should provide a valid command definition for the profile validate command based on our test profile type 1`] = ` -Object { - "aliases": Array [ - "type-a", - ], - "children": Array [], - "customize": Object { - "profileTypeIdentifier": "type-a", - }, - "deprecatedReplacement": "Edit your Zowe V2 configuration - zowe.config.json", - "description": "Test the validity of a type-a profile.", - "name": "type-a-profile", - "options": Array [ - Object { - "aliases": Array [ - "plan", - "p", - ], - "description": "Instead of validating your profile, print out a table of the tasks used for validation. This will explain the different services and functionality that will be tested during profile validation.", - "name": "print-plan-only", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "Specifies the name of the type-a profile to be deleted. You can also load this profile by using the name on commands that support the \\"--type-a-profile\\" option.", - "name": "profileName", - "required": false, - "type": "string", - }, - ], - "summary": "Test the validity of a type-a profile.", - "type": "command", -} -`; diff --git a/packages/imperative/src/cmd/__tests__/profiles/profileHandlers/AddTwoNumbersHandler.ts b/packages/imperative/src/cmd/__tests__/profiles/profileHandlers/AddTwoNumbersHandler.ts deleted file mode 100644 index 0f3db4eef3..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/profileHandlers/AddTwoNumbersHandler.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandHandler, IHandlerParameters } from "../../../"; - -export default class AddTwoNumbersHandler implements ICommandHandler { - public async process(params: IHandlerParameters): Promise { - const sum = params.arguments.a + params.arguments.b; - params.response.console.log("updated sum to: " + sum); - params.response.data.setObj({sum}); - } -} diff --git a/packages/imperative/src/cmd/__tests__/profiles/profileHandlers/DoNothingHandler.ts b/packages/imperative/src/cmd/__tests__/profiles/profileHandlers/DoNothingHandler.ts deleted file mode 100644 index ab19d2da81..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/profileHandlers/DoNothingHandler.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandHandler, IHandlerParameters } from "../../../"; - -export default class DoNothingHandler implements ICommandHandler { - public async process(params: IHandlerParameters): Promise { - params.response.console.log("Doing nothing "); - params.response.data.setObj({}); - } -} diff --git a/packages/imperative/src/cmd/__tests__/profiles/profileHandlers/ThrowErrorHandler.ts b/packages/imperative/src/cmd/__tests__/profiles/profileHandlers/ThrowErrorHandler.ts deleted file mode 100644 index 021b5f32d2..0000000000 --- a/packages/imperative/src/cmd/__tests__/profiles/profileHandlers/ThrowErrorHandler.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandHandler, IHandlerParameters } from "../../../"; - -export default class ThrowErrorHandler implements ICommandHandler { - public async process(params: IHandlerParameters): Promise { - throw new Error("threw an error"); - } -} diff --git a/packages/imperative/src/cmd/__tests__/utils/CommandUtils.unit.test.ts b/packages/imperative/src/cmd/__tests__/utils/CommandUtils.unit.test.ts index 8286d543d4..481617c959 100644 --- a/packages/imperative/src/cmd/__tests__/utils/CommandUtils.unit.test.ts +++ b/packages/imperative/src/cmd/__tests__/utils/CommandUtils.unit.test.ts @@ -15,7 +15,8 @@ import { ICommandOptionDefinition } from "../../src/doc/option/ICommandOptionDef import { COMPLEX_COMMAND, COMPLEX_COMMAND_WITH_ALIASES, MULTIPLE_GROUPS } from "../__resources__/CommandDefinitions"; import { TestLogger } from "../../../../__tests__/src/TestLogger"; import { inspect } from "util"; -import { CommandUtils, ICommandTreeEntry } from "../../"; +import { CommandUtils } from "../../src/utils/CommandUtils"; +import { ICommandTreeEntry } from "../../src/utils/CommandUtils"; import { cloneDeep } from "lodash"; // UnitTestUtils.replaceIt(); @@ -89,8 +90,7 @@ describe("Command Utils", () => { }); it("We should be able to flatten a nested command tree with aliases for display and searching purposes", () => { - // eslint-disable-next-line deprecation/deprecation - const flatten: ICommandTreeEntry[] = CommandUtils.flattenCommandTreeWithAliases(COMPLEX_COMMAND_WITH_ALIASES); + const flatten: ICommandTreeEntry[] = CommandUtils.flattenCommandTree(COMPLEX_COMMAND_WITH_ALIASES); TestLogger.info("Flattened Command Tree:\n" + inspect(flatten)); expect(flatten).toMatchSnapshot(); }); diff --git a/packages/imperative/src/cmd/__tests__/utils/__snapshots__/CommandUtils.unit.test.ts.snap b/packages/imperative/src/cmd/__tests__/utils/__snapshots__/CommandUtils.unit.test.ts.snap index 36b6b6ad5e..d535a0a181 100644 --- a/packages/imperative/src/cmd/__tests__/utils/__snapshots__/CommandUtils.unit.test.ts.snap +++ b/packages/imperative/src/cmd/__tests__/utils/__snapshots__/CommandUtils.unit.test.ts.snap @@ -377,162 +377,6 @@ Array [ "type": "group", }, }, - Object { - "command": Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - "fullName": "test-group tc", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, Object { "command": Object { "aliases": Array [ @@ -921,7 +765,7 @@ Array [ ], "type": "command", }, - "fullName": "test-group test-group-2 tc", + "fullName": "test-group test-group-2 test-command-one", "tree": Object { "aliases": Array [ "tg", @@ -1044,164 +888,8 @@ Array [ }, Object { "command": Object { - "aliases": Array [ - "tc", - ], "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - "fullName": "test-group test-group-2 test-command-one", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, - Object { - "command": Object { - "description": "my command", - "name": "test-command-two", + "name": "test-command-two", "options": Array [ Object { "aliases": Array [ @@ -1351,2548 +1039,9 @@ Array [ "type": "group", }, }, - Object { - "command": Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - "fullName": "test-group tg2", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, - Object { - "command": Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - "fullName": "test-group tg2 tc", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, - Object { - "command": Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - "fullName": "test-group tg2 test-command-one", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, - Object { - "command": Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - "fullName": "test-group tg2 test-command-two", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, - Object { - "command": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - "fullName": "tg", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, - Object { - "command": Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - "fullName": "tg tc", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, - Object { - "command": Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - "fullName": "tg test-command", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, - Object { - "command": Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - "fullName": "tg test-group-2", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, - Object { - "command": Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - "fullName": "tg test-group-2 tc", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, - Object { - "command": Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - "fullName": "tg test-group-2 test-command-one", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, - Object { - "command": Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - "fullName": "tg test-group-2 test-command-two", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, - Object { - "command": Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - "fullName": "tg tg2", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, - Object { - "command": Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - "fullName": "tg tg2 tc", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, - Object { - "command": Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - "fullName": "tg tg2 test-command-one", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, - Object { - "command": Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - "fullName": "tg tg2 test-command-two", - "tree": Object { - "aliases": Array [ - "tg", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional1", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "aliases": Array [ - "tg2", - ], - "children": Array [ - Object { - "aliases": Array [ - "tc", - ], - "description": "my command", - "name": "test-command-one", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - Object { - "description": "my command", - "name": "test-command-two", - "options": Array [ - Object { - "aliases": Array [ - "to", - ], - "description": "the option", - "name": "test-option", - "type": "string", - }, - Object { - "aliases": Array [ - "tb", - ], - "description": "the boolean option", - "name": "test-boolean", - "type": "boolean", - }, - ], - "positionals": Array [ - Object { - "description": "the positional option", - "name": "positional2", - "required": false, - "type": "string", - }, - ], - "type": "command", - }, - ], - "description": "my group", - "name": "test-group-2", - "type": "group", - }, - ], - "description": "my group", - "name": "test-group", - "type": "group", - }, - }, ] `; -exports[`Command Utils We should not be able get the full command name from the flattened tree 1 1`] = `"test-command"`; +exports[`Command Utils We should not be able get the full command name from the flattened tree 1 1`] = `"test-outer-group test-command"`; -exports[`Command Utils We should not be able get the full command name from the flattened tree 2 1`] = `"test-command"`; +exports[`Command Utils We should not be able get the full command name from the flattened tree 2 1`] = `"test-outer-group test-command"`; diff --git a/packages/imperative/src/cmd/__tests__/yargs/YargsConfigurer.unit.test.ts b/packages/imperative/src/cmd/__tests__/yargs/YargsConfigurer.unit.test.ts index 6c3b0c7049..45ce0c0c45 100644 --- a/packages/imperative/src/cmd/__tests__/yargs/YargsConfigurer.unit.test.ts +++ b/packages/imperative/src/cmd/__tests__/yargs/YargsConfigurer.unit.test.ts @@ -10,7 +10,8 @@ */ import { CommandProcessor } from "../../src/CommandProcessor"; -import { Constants, ImperativeConfig, YargsConfigurer } from "../../.."; +import { Constants, ImperativeConfig } from "../../.."; +import { YargsConfigurer } from "../../src/yargs/YargsConfigurer"; jest.mock("yargs"); jest.mock("../../src/CommandProcessor"); @@ -19,7 +20,7 @@ describe("YargsConfigurer tests", () => { it("should build a failure message", () => { const config = new YargsConfigurer({ name: "any", description: "any", type: "command", children: []}, - undefined, undefined, undefined, undefined, undefined, "fake", "fake", "ZOWE", "fake"); + undefined, undefined as any, undefined as any, undefined as any, "fake", "fake", "ZOWE", "fake"); ImperativeConfig.instance.commandLine = "some-command"; @@ -30,13 +31,13 @@ describe("YargsConfigurer tests", () => { it("should get response format from --response-format-json option", () => { const mockedYargs = require("yargs"); - const invokeSpy = jest.spyOn(CommandProcessor.prototype, "invoke").mockResolvedValue(undefined); + const invokeSpy = jest.spyOn(CommandProcessor.prototype, "invoke").mockResolvedValue(undefined as any); jest.spyOn(mockedYargs, "command").mockImplementation((obj: any) => { obj.handler({ _: ["abc"], [Constants.JSON_OPTION]: true }); }); const config = new YargsConfigurer({ name: "any", description: "any", type: "command", children: []}, - mockedYargs, undefined, undefined, { getHelpGenerator: jest.fn() }, undefined, "fake", "fake", "ZOWE", "fake"); + mockedYargs, undefined as any, { getHelpGenerator: jest.fn() }, undefined as any, "fake", "fake", "ZOWE", "fake"); config.configure(); expect(invokeSpy).toHaveBeenCalledTimes(1); @@ -52,7 +53,7 @@ describe("YargsConfigurer tests", () => { */ const configureYargsTwice = () => { const config = new YargsConfigurer({ name: "any", description: "any", type: "command", children: []}, - mockedYargs, undefined, undefined, { getHelpGenerator: jest.fn() }, undefined, "fake", "fake", "ZOWE", "fake"); + mockedYargs, undefined as any, { getHelpGenerator: jest.fn() }, undefined as any, "fake", "fake", "ZOWE", "fake"); buildFailedCmdDefSpy = jest.spyOn(config as any, "buildFailedCommandDefinition"); ImperativeConfig.instance.commandLine = "first-command"; diff --git a/packages/imperative/src/cmd/index.ts b/packages/imperative/src/cmd/index.ts index 98b2d91411..d09801e1dc 100644 --- a/packages/imperative/src/cmd/index.ts +++ b/packages/imperative/src/cmd/index.ts @@ -13,8 +13,8 @@ export * from "./src/doc/profiles/definition/ICommandProfileSchema"; export * from "./src/doc/profiles/definition/ICommandProfileProperty"; export * from "./src/doc/profiles/definition/ICommandProfileTypeConfiguration"; export * from "./src/doc/handler/ICommandHandler"; -export * from "./src/doc/handler/ICommandHandlerResponseChecker"; -export * from "./src/doc/handler/ICommandHandlerResponseValidator"; +// export * from "./src/doc/handler/ICommandHandlerResponseChecker"; +// export * from "./src/doc/handler/ICommandHandlerResponseValidator"; export * from "./src/doc/handler/IHandlerParameters"; export * from "./src/doc/handler/IChainedHandlerEntry"; export * from "./src/doc/handler/IChainedHandlerArgumentMapping"; @@ -26,8 +26,8 @@ export * from "./src/doc/option/ICommandPositionalDefinition"; export * from "./src/doc/response/response/ICommandResponse"; export * from "./src/doc/response/parms/ICommandResponseParms"; -export * from "./src/doc/response/response/ICommandValidatorError"; -export * from "./src/doc/response/response/ICommandValidatorResponse"; +// export * from "./src/doc/response/response/ICommandValidatorError"; +// export * from "./src/doc/response/response/ICommandValidatorResponse"; export * from "./src/doc/ICommandDefinition"; export * from "./src/doc/ICommandDefinitionPassOn"; @@ -36,45 +36,40 @@ export * from "./src/doc/IPartialCommandDefinition"; export * from "./src/doc/args/ICommandArguments"; -export * from "./src/handlers/FailedCommandHandler"; +// export * from "./src/handlers/FailedCommandHandler"; -export * from "./src/help/abstract/AbstractHelpGenerator"; -export * from "./src/help/abstract/AbstractHelpGeneratorFactory"; +// export * from "./src/help/abstract/AbstractHelpGenerator"; +// export * from "./src/help/abstract/AbstractHelpGeneratorFactory"; -export * from "./src/help/doc/IHelpGeneratorFactory"; +// export * from "./src/help/doc/IHelpGeneratorFactory"; export * from "./src/help/doc/IHelpGeneratorFactoryParms"; export * from "./src/help/doc/IHelpGeneratorParms"; export * from "./src/help/DefaultHelpGenerator"; -export * from "./src/help/HelpConstants"; -export * from "./src/help/HelpGeneratorFactory"; -export * from "./src/help/doc/IHelpGenerator"; +// export * from "./src/help/HelpConstants"; +// export * from "./src/help/HelpGeneratorFactory"; +// export * from "./src/help/doc/IHelpGenerator"; +// export * from "./src/help/WebHelpManager"; export * from "./src/help/WebHelpGenerator"; -export * from "./src/help/WebHelpManager"; export * from "./src/doc/profiles/definition/ICommandProfile"; export * from "./src/doc/profiles/definition/ICommandProfileTypeConfiguration"; -export * from "./src/profiles/CliProfileManager"; +// export * from "./src/syntax/SyntaxValidator"; -export * from "./src/syntax/SyntaxValidator"; +// export * from "./src/utils/CommandUtils"; +// export * from "./src/utils/SharedOptions"; -export * from "./src/utils/CommandUtils"; -export * from "./src/utils/SharedOptions"; +// export * from "./src/yargs/doc/IYargsParms"; +// export * from "./src/yargs/doc/IYargsResponse"; -export * from "./src/yargs/doc/IYargsParms"; -export * from "./src/yargs/doc/IYargsResponse"; +// export * from "./src/yargs/AbstractCommandYargs"; +// export * from "./src/yargs/CommandYargs"; +// export * from "./src/yargs/GroupCommandYargs"; +// export * from "./src/yargs/YargsConfigurer"; +// export * from "./src/yargs/YargsDefiner"; -export * from "./src/yargs/AbstractCommandYargs"; -export * from "./src/yargs/CommandYargs"; -export * from "./src/yargs/GroupCommandYargs"; -export * from "./src/yargs/YargsConfigurer"; -export * from "./src/yargs/YargsDefiner"; - -export * from "./src/CommandPreparer"; -export * from "./src/CommandProcessor"; -export * from "./src/response/CommandResponse"; - -export * from "./src/profiles/CommandProfiles"; +// export * from "./src/CommandPreparer"; +// export * from "./src/CommandProcessor"; export * from "./src/response/CommandResponse"; export * from "./src/response/HandlerResponse"; diff --git a/packages/imperative/src/cmd/src/CommandPreparer.ts b/packages/imperative/src/cmd/src/CommandPreparer.ts index 5903f2533a..ef35c13c69 100644 --- a/packages/imperative/src/cmd/src/CommandPreparer.ts +++ b/packages/imperative/src/cmd/src/CommandPreparer.ts @@ -511,10 +511,10 @@ export class CommandPreparer { if (definition.profile.optional) { types = types.concat(definition.profile.optional); } - const profileOptions: string[] = types.filter((type) => ( + const profileOptions: string[] = types.filter((type) => !Array.isArray(definition.profile.suppressOptions) ? true : definition.profile.suppressOptions.indexOf(type) < 0 - )); + ); profileOptions.forEach((profOpt) => { const [profOptName, profOptAlias] = ProfileUtils.getProfileOptionAndAlias(profOpt); @@ -617,7 +617,7 @@ export class CommandPreparer { /** * Either merge/append or overwrite the field in the definition. */ - const cloned = (trait.value != null) ? + const cloned = trait.value != null ? JSON.parse(JSON.stringify(trait.value)) : undefined; if (cloned == null) { diff --git a/packages/imperative/src/cmd/src/CommandProcessor.ts b/packages/imperative/src/cmd/src/CommandProcessor.ts index d468e1beea..a3d0f077d0 100644 --- a/packages/imperative/src/cmd/src/CommandProcessor.ts +++ b/packages/imperative/src/cmd/src/CommandProcessor.ts @@ -17,20 +17,16 @@ import { ICommandHandler } from "./doc/handler/ICommandHandler"; import { couldNotInstantiateCommandHandler, unexpectedCommandError } from "../../messages"; import { SharedOptions } from "./utils/SharedOptions"; import { IImperativeError, ImperativeError } from "../../error"; -import { IProfileManagerFactory, ProfileUtils } from "../../profiles"; import { SyntaxValidator } from "./syntax/SyntaxValidator"; -import { CommandProfileLoader } from "./profiles/CommandProfileLoader"; -import { ICommandProfileTypeConfiguration } from "./doc/profiles/definition/ICommandProfileTypeConfiguration"; import { IHelpGenerator } from "./help/doc/IHelpGenerator"; -import { ICommandPrepared } from "./doc/response/response/ICommandPrepared"; import { CommandResponse } from "./response/CommandResponse"; import { ICommandResponse } from "./doc/response/response/ICommandResponse"; -import { Logger, LoggerUtils } from "../../logger"; +import { Logger } from "../../logger"; import { IInvokeCommandParms } from "./doc/parms/IInvokeCommandParms"; import { ICommandProcessorParms } from "./doc/processor/ICommandProcessorParms"; import { ImperativeExpect } from "../../expect"; import { inspect } from "util"; -import { EnvFileUtils, ImperativeConfig, NextVerFeatures, TextUtils } from "../../utilities"; +import { EnvFileUtils, ImperativeConfig, TextUtils } from "../../utilities"; import * as nodePath from "path"; import * as os from "os"; import * as stream from "stream"; @@ -41,7 +37,6 @@ import { Constants } from "../../constants"; import { ICommandArguments } from "./doc/args/ICommandArguments"; import { CliUtils } from "../../utilities/src/CliUtils"; import { WebHelpManager } from "./help/WebHelpManager"; -import { ICommandProfile } from "./doc/profiles/definition/ICommandProfile"; import { Config } from "../../config/src/Config"; import { ConfigUtils } from "../../config/src/ConfigUtils"; import { ConfigConstants } from "../../config/src/ConfigConstants"; @@ -62,13 +57,6 @@ interface IResolvedArgsResponse { */ commandValues?: ICommandArguments; - /** - * Whether we're using old profiles or config - * @type {(`v1` | `v2`)} - * @memberof IResolvedArgsResponse - */ - profileVersion?: `v1` | `v2`; - /** * The profiles that are required * @type {string[]} @@ -163,13 +151,6 @@ export class CommandProcessor { * @memberof CommandProcessor */ private mHelpGenerator: IHelpGenerator; - /** - * The profile manager to use when loading profiles for commands - * @private - * @type {IProfileManagerFactory} - * @memberof CommandProcessor - */ - private mProfileManagerFactory: IProfileManagerFactory; /** * Imperative Logger instance for logging from the command processor. * @private @@ -201,11 +182,9 @@ export class CommandProcessor { ImperativeExpect.toNotBeNullOrUndefined(params, `${CommandProcessor.ERROR_TAG} No parameters supplied to constructor.`); this.mDefinition = params.definition; ImperativeExpect.toNotBeNullOrUndefined(this.mDefinition, `${CommandProcessor.ERROR_TAG} No command definition supplied.`); - this.mFullDefinition = (params.fullDefinition == null) ? this.mDefinition : params.fullDefinition; + this.mFullDefinition = params.fullDefinition == null ? this.mDefinition : params.fullDefinition; this.mHelpGenerator = params.helpGenerator; ImperativeExpect.toNotBeNullOrUndefined(this.mHelpGenerator, `${CommandProcessor.ERROR_TAG} No help generator supplied.`); - this.mProfileManagerFactory = params.profileManagerFactory; - ImperativeExpect.toNotBeNullOrUndefined(this.mProfileManagerFactory, `${CommandProcessor.ERROR_TAG} No profile manager factory supplied.`); if (this.mDefinition.type === "command" && this.mDefinition.chainedHandlers == null) { ImperativeExpect.keysToBeDefinedAndNonBlank(this.mDefinition, ["handler"], `${CommandProcessor.ERROR_TAG} ` + `The definition supplied is of type "command", ` + @@ -283,19 +262,9 @@ export class CommandProcessor { return this.mConfig; } - /** - * Accessor for the profile manager factory in use for this command processor. - * @readonly - * @type {IProfileManagerFactory} - * @memberof CommandProcessor - */ - get profileFactory(): IProfileManagerFactory { - return this.mProfileManagerFactory; - } - /** * Obtain a copy of the command definition - * @return {ICommandDefinition}: The Bright Commands definition document. + * @return {ICommandDefinition}: The Zowe Commands definition document. */ get definition(): ICommandDefinition { return JSON.parse(JSON.stringify(this.mDefinition)); @@ -303,7 +272,7 @@ export class CommandProcessor { /** * Obtain a copy of the command definition - * @return {ICommandDefinition}: The Bright Commands definition document. + * @return {ICommandDefinition}: The Zowe Commands definition document. */ get fullDefinition(): ICommandDefinition { return JSON.parse(JSON.stringify(this.mFullDefinition)); @@ -374,7 +343,7 @@ export class CommandProcessor { `${CommandProcessor.ERROR_TAG} invoke(): No parameters supplied.`); ImperativeExpect.toNotBeNullOrUndefined(params.arguments, `${CommandProcessor.ERROR_TAG} invoke(): No command arguments supplied.`); - params.responseFormat = (params.responseFormat == null) ? "default" : params.responseFormat; + params.responseFormat = params.responseFormat == null ? "default" : params.responseFormat; const responseOptions: string[] = ["default", "json"]; ImperativeExpect.toBeOneOf(params.responseFormat, responseOptions, `${CommandProcessor.ERROR_TAG} invoke(): Response format must be one of the following: ${responseOptions.join(",")}`); @@ -436,7 +405,7 @@ export class CommandProcessor { prepareResponse.succeeded(); // Prepare for command processing - load profiles, stdin, etc. - let prepared: ICommandPrepared; + let preparedArgs: ICommandArguments; try { // Build the response object, base args object, and the entire array of options for this command // Assume that the command succeed, it will be marked otherwise under the appropriate failure conditions @@ -469,7 +438,7 @@ export class CommandProcessor { } this.log.info(`Preparing (loading profiles, reading stdin, etc.) execution of "${this.definition.name}" command...`); - prepared = await this.prepare(prepareResponse, params.arguments); + preparedArgs = await this.prepare(prepareResponse, params.arguments); } catch (prepareErr) { // Indicate that the command has failed @@ -502,7 +471,7 @@ export class CommandProcessor { } // Recreate the response object with the update params from prepare. - params.arguments = prepared.args; + params.arguments = preparedArgs; const response = this.constructResponseObject(params); response.succeeded(); @@ -515,37 +484,35 @@ export class CommandProcessor { // convert if positional is an array designated by "..." const positionalName = positional.name.replace("...", ""); // check if value provided - if (prepared.args[positionalName] != null) { + if (preparedArgs[positionalName] != null) { // string processing - if (typeof prepared.args[positionalName] === "string" && - prepared.args[positionalName].toUpperCase() === this.promptPhrase.toUpperCase()) { + if (typeof preparedArgs[positionalName] === "string" && + preparedArgs[positionalName].toUpperCase() === this.promptPhrase.toUpperCase()) { // prompt has been requested for a positional this.log.debug("Prompting for positional %s which was requested by passing the value %s", positionalName, this.promptPhrase); - prepared.args[positionalName] = + preparedArgs[positionalName] = await response.console.prompt(`"${positionalName}" Description: ` + `${positional.description}\nPlease enter "${positionalName}":`, { hideText: true, secToWait: 0 }); } // array processing - else { - if ((prepared.args[positionalName] != null && - (Array.isArray(prepared.args[positionalName])) && - prepared.args[positionalName][0] != null && - typeof prepared.args[positionalName][0] === "string" && - (prepared.args[positionalName][0].toUpperCase() === this.promptPhrase.toUpperCase()))) { - // prompt has been requested for a positional - this.log.debug("Prompting for positional %s which was requested by passing the value %s", - prepared.args[positionalName][0], this.promptPhrase); - prepared.args[positionalName][0] = - await response.console.prompt(`"${positionalName}" Description: ` + - `${positional.description}\nPlease enter "${positionalName}":`, - { hideText: true, secToWait: 0 }); - // prompting enters as string but need to place it in array - - const array = prepared.args[positionalName][0].split(" "); - prepared.args[positionalName] = array; - } + else if (preparedArgs[positionalName] != null && + Array.isArray(preparedArgs[positionalName]) && + preparedArgs[positionalName][0] != null && + typeof preparedArgs[positionalName][0] === "string" && + preparedArgs[positionalName][0].toUpperCase() === this.promptPhrase.toUpperCase()) { + // prompt has been requested for a positional + this.log.debug("Prompting for positional %s which was requested by passing the value %s", + preparedArgs[positionalName][0], this.promptPhrase); + preparedArgs[positionalName][0] = + await response.console.prompt(`"${positionalName}" Description: ` + + `${positional.description}\nPlease enter "${positionalName}":`, + { hideText: true, secToWait: 0 }); + // prompting enters as string but need to place it in array + + const array = preparedArgs[positionalName][0].split(" "); + preparedArgs[positionalName] = array; } } } @@ -554,49 +521,47 @@ export class CommandProcessor { if (this.definition.options != null && this.definition.options.length > 0) { for (const option of this.definition.options) { // check if value provided - if (prepared.args[option.name] != null) { + if (preparedArgs[option.name] != null) { // string processing - if (typeof prepared.args[option.name] === "string" && - prepared.args[option.name].toUpperCase() === this.promptPhrase.toUpperCase()) { + if (typeof preparedArgs[option.name] === "string" && + preparedArgs[option.name].toUpperCase() === this.promptPhrase.toUpperCase()) { // prompt has been requested for an --option this.log.debug("Prompting for option %s which was requested by passing the value %s", option.name, this.promptPhrase); - prepared.args[option.name] = + preparedArgs[option.name] = await response.console.prompt(`"${option.name}" Description: ` + `${option.description}\nPlease enter "${option.name}":`, { hideText: true, secToWait: 0 }); const camelCase = CliUtils.getOptionFormat(option.name).camelCase; - prepared.args[camelCase] = prepared.args[option.name]; + preparedArgs[camelCase] = preparedArgs[option.name]; if (option.aliases != null) { for (const alias of option.aliases) { // set each alias of the args object as well - prepared.args[alias] = prepared.args[option.name]; + preparedArgs[alias] = preparedArgs[option.name]; } } } // array processing - else { - if (((Array.isArray(prepared.args[option.name])) && - prepared.args[option.name][0] != null && - typeof prepared.args[option.name][0] === "string" && - (prepared.args[option.name][0].toUpperCase() === this.promptPhrase.toUpperCase()))) { - // prompt has been requested for an --option - this.log.debug("Prompting for option %s which was requested by passing the value %s", - option.name, this.promptPhrase); - prepared.args[option.name][0] = - await response.console.prompt(`"${option.name}" Description: ` + - `${option.description}\nPlease enter "${option.name}":`, - { hideText: true, secToWait: 0 }); - - const array = prepared.args[option.name][0].split(" "); - prepared.args[option.name] = array; - const camelCase = CliUtils.getOptionFormat(option.name).camelCase; - prepared.args[camelCase] = prepared.args[option.name]; - if (option.aliases != null) { - for (const alias of option.aliases) { - // set each alias of the args object as well - prepared.args[alias] = prepared.args[option.name]; - } + else if (Array.isArray(preparedArgs[option.name]) && + preparedArgs[option.name][0] != null && + typeof preparedArgs[option.name][0] === "string" && + preparedArgs[option.name][0].toUpperCase() === this.promptPhrase.toUpperCase()) { + // prompt has been requested for an --option + this.log.debug("Prompting for option %s which was requested by passing the value %s", + option.name, this.promptPhrase); + preparedArgs[option.name][0] = + await response.console.prompt(`"${option.name}" Description: ` + + `${option.description}\nPlease enter "${option.name}":`, + { hideText: true, secToWait: 0 }); + + const array = preparedArgs[option.name][0].split(" "); + preparedArgs[option.name] = array; + const camelCase = CliUtils.getOptionFormat(option.name).camelCase; + preparedArgs[camelCase] = preparedArgs[option.name]; + if (option.aliases != null) { + for (const alias of option.aliases) { + // set each alias of the args object as well + preparedArgs[alias] = preparedArgs[option.name]; } } } @@ -622,7 +587,7 @@ export class CommandProcessor { // Validate that the syntax is correct for the command let validator: ICommandValidatorResponse; try { - validator = await this.validate(prepared.args, response); + validator = await this.validate(preparedArgs, response); } catch (e) { const errMsg: string = `Unexpected syntax validation error`; const errReason: string = errMsg + ": " + e.message; @@ -657,9 +622,8 @@ export class CommandProcessor { const handlerParms: IHandlerParameters = { response, - profiles: prepared.profiles, - arguments: prepared.args, - positionals: prepared.args._, + arguments: preparedArgs, + positionals: preparedArgs._, definition: this.definition, fullDefinition: this.fullDefinition, stdin: this.getStdinStream() @@ -723,16 +687,15 @@ export class CommandProcessor { try { await handler.process({ response: chainedResponse, - profiles: prepared.profiles, arguments: ChainedHandlerService.getArguments( this.mCommandRootName, this.definition.chainedHandlers, chainedHandlerIndex, chainedResponses, - prepared.args, + preparedArgs, this.log ), - positionals: prepared.args._, + positionals: preparedArgs._, definition: this.definition, fullDefinition: this.fullDefinition, stdin: this.getStdinStream(), @@ -787,21 +750,12 @@ export class CommandProcessor { showSecure = true; } - // if config exists and a layer exists, use config - let useConfig = false; - this.mConfig?.layers.forEach((layer) => { - if (layer.exists) { - useConfig = true; - } - }); - /** * Begin building response object */ const showInputsOnly: IResolvedArgsResponse = { - commandValues: {} as ICommandArguments, - profileVersion: useConfig ? `v2` : `v1`, + commandValues: {} as ICommandArguments }; /** @@ -814,30 +768,21 @@ export class CommandProcessor { const configSecureProps: string[] = []; /** - * If using config, then we need to get the secure properties from the config + * Need to get the secure properties from the config */ - if (useConfig) { - - const combinedProfiles = [ ...showInputsOnly.requiredProfiles ?? [], ...showInputsOnly.optionalProfiles ?? [] ]; - combinedProfiles.forEach((profile) => { - const name = ConfigUtils.getActiveProfileName(profile, commandParameters.arguments); // get profile name - const props = this.mConfig.api.secure.securePropsForProfile(name); // get secure props - for (const propName of props) { - configSecureProps.push(...Object.values(CliUtils.getOptionFormat(propName))); // add multiple cases to list - } - }); - } + const combinedProfiles = [ ...showInputsOnly.requiredProfiles ?? [], ...showInputsOnly.optionalProfiles ?? [] ]; + combinedProfiles.forEach((profile) => { + const name = ConfigUtils.getActiveProfileName(profile, commandParameters.arguments); // get profile name + const props = this.mConfig.api.secure.securePropsForProfile(name); // get secure props + for (const propName of props) { + configSecureProps.push(...Object.values(CliUtils.getOptionFormat(propName))); // add multiple cases to list + } + }); /** - * Determine if Zowe V2 Config is in effect. If it is, then we will construct - * a Set of secure fields from its API. If it is not, then we will construct - * a Set of secure fields from the `ConnectionPropsForSessCfg` defaults. + * Construct a Set of secure fields from Zowe Team Config API. */ - const secureInputs: Set = - useConfig ? - new Set([...configSecureProps]) : - new Set([...LoggerUtils.CENSORED_OPTIONS, ...LoggerUtils.SECURE_PROMPT_OPTIONS]); - + const secureInputs: Set = new Set([...configSecureProps]); let censored = false; /** @@ -860,15 +805,11 @@ export class CommandProcessor { /** * Add profile location info */ - if (useConfig) { - this.mConfig?.layers.forEach((layer) => { - if (layer.exists) { - showInputsOnly.locations.push(layer.path); - } - }); - } else { - showInputsOnly.locations.push(nodePath.normalize(ImperativeConfig.instance.cliHome)); - } + this.mConfig?.layers.forEach((layer) => { + if (layer.exists) { + showInputsOnly.locations.push(layer.path); + } + }); /** * Show warning if we censored output and we were not instructed to show secure values @@ -931,15 +872,15 @@ export class CommandProcessor { * the command handler is invoked. * @param {CommandResponse} response: The response object for command messaging. * @param {yargs.Arguments} commandArguments: The arguments specified on the command line. - * @return {Promise}: Promise to fulfill when complete. + * @return {Promise}: Promise to fulfill when complete. */ - private async prepare(response: CommandResponse, commandArguments: Arguments): Promise { + private async prepare(response: CommandResponse, commandArguments: Arguments): Promise { // Construct the imperative arguments - replacement/wrapper for Yargs to insulate handlers against any // changes made to Yargs let args: ICommandArguments = CliUtils.buildBaseArgs(commandArguments); this.log.trace(`Base set of arguments from Yargs parse:\n${inspect(args)}`); - let allOpts = (this.definition.options != null) ? this.definition.options : []; - allOpts = (this.definition.positionals != null) ? allOpts.concat(this.definition.positionals) : allOpts; + let allOpts = this.definition.options != null ? this.definition.options : []; + allOpts = this.definition.positionals != null ? allOpts.concat(this.definition.positionals) : allOpts; this.log.trace(`Set of options and positionals defined on the command:\n${inspect(allOpts)}`); // Extract options supplied via environment variables - we must do this before we load profiles to @@ -954,101 +895,11 @@ export class CommandProcessor { this.log.trace(`Reading stdin for "${this.definition.name}" command...`); await SharedOptions.readStdinIfRequested(commandArguments, response, this.definition.type); - // Build a list of all profile types - this will help us search the CLI - // options for profiles specified by the user - let allTypes: string[] = []; - if (this.definition.profile != null) { - if (this.definition.profile.required != null) - allTypes = allTypes.concat(this.definition.profile.required); - if (this.definition.profile.optional != null) - allTypes = allTypes.concat(this.definition.profile.optional); - } - // Build an object that contains all the options loaded from config - const fulfilled: string[] = []; - let fromCnfg: any = {}; if (this.mConfig != null) { - for (const profileType of allTypes) { - const opt = ProfileUtils.getProfileOptionAndAlias(profileType)[0]; - // If the config contains the requested profiles, then "remember" - // that this type has been fulfilled - so that we do NOT load from - // the traditional profile location - const profileTypePrefix = profileType + "_"; - let p: any = {}; - if (args[opt] != null && this.mConfig.api.profiles.exists(args[opt])) { - fulfilled.push(profileType); - p = this.mConfig.api.profiles.get(args[opt]); - } else if (args[opt] != null && !args[opt].startsWith(profileTypePrefix) && - this.mConfig.api.profiles.exists(profileTypePrefix + args[opt])) { - fulfilled.push(profileType); - p = this.mConfig.api.profiles.get(profileTypePrefix + args[opt]); - } else if (args[opt] == null && - this.mConfig.properties.defaults[profileType] != null && - this.mConfig.api.profiles.exists(this.mConfig.properties.defaults[profileType])) { - fulfilled.push(profileType); - p = this.mConfig.api.profiles.defaultGet(profileType); - } - fromCnfg = { ...p, ...fromCnfg }; - } - } - - // Convert each property extracted from the config to the correct yargs - // style cases for the command handler (kebab and camel) - allOpts.forEach((opt) => { - const cases = CliUtils.getOptionFormat(opt.name); - const profileKebab = fromCnfg[cases.kebabCase]; - const profileCamel = fromCnfg[cases.camelCase]; - - if ((profileCamel !== undefined || profileKebab !== undefined) && - (!Object.prototype.hasOwnProperty.call(args, cases.kebabCase) && - !Object.prototype.hasOwnProperty.call(args, cases.camelCase))) { - - // If both case properties are present in the profile, use the one that matches - // the option name explicitly - const value = (profileKebab !== undefined && profileCamel !== undefined) ? - ((opt.name === cases.kebabCase) ? profileKebab : profileCamel) : - ((profileKebab !== undefined) ? profileKebab : profileCamel); - const keys = CliUtils.setOptionValue(opt.name, - ("aliases" in opt) ? opt.aliases : [], - value - ); - fromCnfg = { ...fromCnfg, ...keys }; - } - }); - - // Merge the arguments from the config into the CLI args - this.log.trace(`Arguments extracted from the config:\n${inspect(fromCnfg)}`); - args = CliUtils.mergeArguments(fromCnfg, args); - - // Load all profiles for the command - this.log.trace(`Loading profiles for "${this.definition.name}" command. ` + - `Profile definitions: ${inspect(this.definition.profile, { depth: null })}`); - - const profiles = await CommandProfileLoader.loader({ - commandDefinition: this.definition, - profileManagerFactory: this.profileFactory - }).loadProfiles(args); - this.log.trace(`Profiles loaded for "${this.definition.name}" command:\n${inspect(profiles, { depth: null })}`); - - // If we have profiles listed on the command definition (the would be loaded already) - // we can extract values from them for options arguments - if (this.definition.profile != null) { - - // "fake out" the cli util to only populate options for profiles - // that have not been fulfilled by the config - const p: ICommandProfile = { - required: [], - optional: [], - suppressOptions: this.definition.profile.suppressOptions - }; - - if (this.definition.profile.required) - p.required = this.definition.profile.required.filter(type => fulfilled.indexOf(type) < 0); - if (this.definition.profile.optional) - p.optional = this.definition.profile.optional.filter(type => fulfilled.indexOf(type) < 0); - - const profArgs = CliUtils.getOptValueFromProfiles(profiles, p, allOpts); - this.log.trace(`Arguments extract from the profile:\n${inspect(profArgs)}`); + // Merge the arguments from the config into the CLI args + const profArgs = CliUtils.getOptValuesFromConfig(this.mConfig, this.definition.profile, args, allOpts); + this.log.trace(`Arguments extracted from the config:\n${inspect(profArgs)}`); args = CliUtils.mergeArguments(profArgs, args); } @@ -1057,7 +908,7 @@ export class CommandProcessor { for (const option of allOpts) { if (option.defaultValue != null && args[option.name] == null && !args[Constants.DISABLE_DEFAULTS_OPTION]) { const defaultedArgs = CliUtils.setOptionValue(option.name, - ("aliases" in option) ? option.aliases : [], + "aliases" in option ? option.aliases : [], option.defaultValue ); args = CliUtils.mergeArguments(args, defaultedArgs); @@ -1070,7 +921,7 @@ export class CommandProcessor { // Log for debugging this.log.trace(`Full argument object constructed:\n${inspect(args)}`); - return { profiles, args }; + return args; } /** @@ -1097,7 +948,7 @@ export class CommandProcessor { return new CommandResponse({ definition: this.definition, args: params.arguments, - silent: (params.silent == null) ? false : params.silent, + silent: params.silent == null ? false : params.silent, responseFormat: params.responseFormat, stream: ImperativeConfig.instance.daemonContext?.stream }); @@ -1212,37 +1063,28 @@ export class CommandProcessor { response.setError(handlerErr.details); // display primary user message - // TODO:V3_ERR_FORMAT - Don't test for env variable in V3 - if (NextVerFeatures.useV3ErrFormat()) { - response.console.error(TextUtils.chalk.red( - "Unable to perform this operation due to the following problem." - )); - // Remove http status in 'message', since the same information was placed in additionalDetails. - response.console.error(TextUtils.chalk.red( - handlerErr.message.replace(/Rest API failure with HTTP\(S\) status \d\d\d\n/, "") - )); - } else { // TODO:V3_ERR_FORMAT - Remove in V3 - response.console.errorHeader("Command Error"); - response.console.error(Buffer.from(handlerErr.message + "\n")); - } + response.console.error(TextUtils.chalk.red( + "Unable to perform this operation due to the following problem." + )); + // Remove http status in 'message', since the same information was placed in additionalDetails. + response.console.error(TextUtils.chalk.red( + handlerErr.message.replace(/Rest API failure with HTTP\(S\) status \d\d\d\n/, "") + )); // display server response - // TODO:V3_ERR_FORMAT - Don't test for env variable in V3 - if (NextVerFeatures.useV3ErrFormat()) { - const responseTitle = "Response From Service"; - if (handlerErr.causeErrors) { - try { - const causeErrorsJson = JSON.parse(handlerErr.causeErrors); + const responseTitle = "Response From Service"; + if (handlerErr.causeErrors) { + try { + const causeErrorsJson = JSON.parse(handlerErr.causeErrors); + response.console.error("\n" + TextUtils.chalk.bold.yellow(responseTitle)); + response.console.error(TextUtils.prettyJson(causeErrorsJson, undefined, false, "")); + } catch (parseErr) { + // causeErrors was not JSON. + const causeErrString: string = handlerErr.causeErrors.toString(); + if (causeErrString.length > 0) { + // output the text value of causeErrors response.console.error("\n" + TextUtils.chalk.bold.yellow(responseTitle)); - response.console.error(TextUtils.prettyJson(causeErrorsJson, undefined, false, "")); - } catch (parseErr) { - // causeErrors was not JSON. - const causeErrString: string = handlerErr.causeErrors.toString(); - if (causeErrString.length > 0) { - // output the text value of causeErrors - response.console.error("\n" + TextUtils.chalk.bold.yellow(responseTitle)); - response.console.error(causeErrString); - } + response.console.error(causeErrString); } } } @@ -1250,12 +1092,7 @@ export class CommandProcessor { // display diagnostic information const diagInfo: string = (handlerErr as ImperativeError).details.additionalDetails; if (diagInfo?.length > 0) { - // TODO:V3_ERR_FORMAT - Don't test for env variable in V3 - if (NextVerFeatures.useV3ErrFormat()) { - response.console.error(TextUtils.chalk.bold.yellow("\nDiagnostic Information")); - } else { // TODO:V3_ERR_FORMAT - Remove in V3 - response.console.errorHeader("Error Details"); - } + response.console.error(TextUtils.chalk.bold.yellow("\nDiagnostic Information")); response.console.error(diagInfo); } diff --git a/packages/imperative/src/cmd/src/doc/ICommandDefinition.ts b/packages/imperative/src/cmd/src/doc/ICommandDefinition.ts index 3343e1cb74..3d8294934d 100644 --- a/packages/imperative/src/cmd/src/doc/ICommandDefinition.ts +++ b/packages/imperative/src/cmd/src/doc/ICommandDefinition.ts @@ -119,7 +119,7 @@ export interface ICommandDefinition { chainedHandlers?: IChainedHandlerEntry[]; /** * The Children for this command - used when the type is provider or group. Use the children to build complex - * nested syntaxes - however bright modules must follow the prescribed command syntax structure for Brightside. + * nested syntaxes - however Zowe modules must follow the prescribed command syntax structure for Zowe. * @type {ICommandDefinition[]} * @memberof ICommandDefinition */ diff --git a/packages/imperative/src/cmd/src/doc/args/ICommandArguments.ts b/packages/imperative/src/cmd/src/doc/args/ICommandArguments.ts index 077840758d..8ba44c5039 100644 --- a/packages/imperative/src/cmd/src/doc/args/ICommandArguments.ts +++ b/packages/imperative/src/cmd/src/doc/args/ICommandArguments.ts @@ -27,10 +27,10 @@ export interface ICommandArguments { $0: string; /** * The set of command segments and positional operands in an array. - * @type {string[]} + * @type {(string | number)[]} * @example ["create", "file", "text.txt"] */ - _: string[]; + _: (string | number)[]; /** * Index signature. */ diff --git a/packages/imperative/src/cmd/src/doc/handler/ICommandHandler.ts b/packages/imperative/src/cmd/src/doc/handler/ICommandHandler.ts index 00c6b16599..c7bc1c7573 100644 --- a/packages/imperative/src/cmd/src/doc/handler/ICommandHandler.ts +++ b/packages/imperative/src/cmd/src/doc/handler/ICommandHandler.ts @@ -10,10 +10,10 @@ */ /** - * Brightside command handlers must implement this interface. + * Zowe command handlers must implement this interface. * * !!!Note: Handlers must "export" the module name via "module.exports=" for the handler to be - * instantiated correctly by the bright command processor. + * instantiated correctly by the Zowe command processor. */ import { IHandlerParameters } from "./IHandlerParameters"; diff --git a/packages/imperative/src/cmd/src/doc/handler/IHandlerParameters.ts b/packages/imperative/src/cmd/src/doc/handler/IHandlerParameters.ts index 31f9050d72..d2c960091f 100644 --- a/packages/imperative/src/cmd/src/doc/handler/IHandlerParameters.ts +++ b/packages/imperative/src/cmd/src/doc/handler/IHandlerParameters.ts @@ -11,7 +11,6 @@ import * as stream from "stream"; import { ICommandDefinition } from "../ICommandDefinition"; -import { CommandProfiles } from "../../profiles/CommandProfiles"; import { IHandlerResponseApi } from "../../doc/response/api/handler/IHandlerResponseApi"; import { ICommandArguments } from "../args/ICommandArguments"; @@ -47,20 +46,10 @@ export interface IHandlerParameters { /** * The positional options specified by the user on the command line. - * @type {string[]} + * @type {(string | number)[]} * @memberof IHandlerParameters */ - positionals: string[]; - - /** - * The set of profiles loaded for this command handler - the map is built with the key being the type and it - * returns the set of profiles loaded of that type. Multiple profiles can be loaded of the same type - depending - * on the request and the 0th entry is the first loaded. - * @deprecated This API only loads v1 profiles. To load v2 profiles, use `ImperativeConfig.instance.config.api.profiles`. - * @type {Map} - * @memberof IHandlerParameters - */ - profiles: CommandProfiles; + positionals: (string | number)[]; /** * The command definition node that defines the command being issued. diff --git a/packages/imperative/src/cmd/src/doc/processor/ICommandProcessorParms.ts b/packages/imperative/src/cmd/src/doc/processor/ICommandProcessorParms.ts index 82ffd3fd02..0f94aec062 100644 --- a/packages/imperative/src/cmd/src/doc/processor/ICommandProcessorParms.ts +++ b/packages/imperative/src/cmd/src/doc/processor/ICommandProcessorParms.ts @@ -11,8 +11,6 @@ import { ICommandDefinition } from "../ICommandDefinition"; import { IHelpGenerator } from "../../help/doc/IHelpGenerator"; -import { IProfileManagerFactory } from "../../../../profiles"; -import { ICommandProfileTypeConfiguration } from "../../../src/doc/profiles/definition/ICommandProfileTypeConfiguration"; import { Config } from "../../../../config"; import { IDaemonContext } from "../../../../imperative/src/doc/IDaemonContext"; @@ -36,13 +34,6 @@ export interface ICommandProcessorParms { * @memberof ICommandProcessorParms */ helpGenerator: IHelpGenerator; - /** - * The profile manager factory allows the command processor to obtain an instance of the profile manager for - * the command being issued. - * @type {IProfileManagerFactory} - * @memberof ICommandProcessorParms - */ - profileManagerFactory: IProfileManagerFactory; /** * The root command name for the CLI - used in help generation, etc. * @type {string} diff --git a/packages/imperative/src/cmd/src/doc/profiles/definition/ICommandProfileTypeConfiguration.ts b/packages/imperative/src/cmd/src/doc/profiles/definition/ICommandProfileTypeConfiguration.ts index a2e86a1aa8..ad77a27e7d 100644 --- a/packages/imperative/src/cmd/src/doc/profiles/definition/ICommandProfileTypeConfiguration.ts +++ b/packages/imperative/src/cmd/src/doc/profiles/definition/ICommandProfileTypeConfiguration.ts @@ -11,7 +11,6 @@ import { ICommandProfileSchema } from "./ICommandProfileSchema"; import { IProfileTypeConfiguration } from "../../../../.."; -import { ICommandExampleDefinition } from "../../ICommandExampleDefinition"; import { ICommandProfileAuthConfig } from "./ICommandProfileAuthConfig"; /** @@ -22,56 +21,6 @@ import { ICommandProfileAuthConfig } from "./ICommandProfileAuthConfig"; * @extends {IProfileTypeConfiguration} */ export interface ICommandProfileTypeConfiguration extends IProfileTypeConfiguration { - /** - * A handler module which Imperative will require(). - * The module's default export should be a handler that calls - * appendResponseObject on the provided commandParameters.response - * You do NOT have to implement writing the profile to disk -- you only have to produce - * the final profile object that you would like to be written. - * - * - * This is only required if finished profile can't be created directly from the arguments, e.g. - * if you have --user and --password and need to always transform it into a basic auth - * - * - * If omitted, Imperative will just write all fields present from the schema into the profile - * without requiring a module - * - * @type {string} - * @memberof IProfileTypeConfiguration - */ - createProfileFromArgumentsHandler?: string; - /** - * The module's default export should be a handler that calls appendResponseObject on the provided - * commandParameters.response You do NOT have to implement writing the profile to disk -- you only have to produce - * the final profile object that you would like to be written. - * - * This is only required if finished updated profile can't be created directly from the arguments, e.g. - * if certain fields that the user might specify mean that other fields should be deleted or updated. - * - * If omitted, Imperative will load the old profile, overwrite any fields specified by the user, - * and write the updated profile to disk. - * - * @type {string} - * @memberof IProfileTypeConfiguration - */ - updateProfileFromArgumentsHandler?: string; - /** - * Examples to be displayed in the help text for the auto generated create profile command. - * - * @type {ICommandExampleDefinition[]} - * @memberof IProfileTypeConfiguration - */ - createProfileExamples?: ICommandExampleDefinition[]; - - /** - * Examples to be displayed in the help text for the auto generated update profile command. - * - * @type {ICommandExampleDefinition[]} - * @memberof IProfileTypeConfiguration - */ - updateProfileExamples?: ICommandExampleDefinition[]; - /** * The JSON schema document. The schema document provides a way to enforce the contents of a profile. The schema * conforms exactly to the JSON schema specification. You must supply all properties you would like validated diff --git a/packages/imperative/src/cmd/src/doc/profiles/parms/ICliLoadAllProfiles.ts b/packages/imperative/src/cmd/src/doc/profiles/parms/ICliLoadAllProfiles.ts deleted file mode 100644 index bf6cd2f640..0000000000 --- a/packages/imperative/src/cmd/src/doc/profiles/parms/ICliLoadAllProfiles.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ILoadAllProfiles } from "../../../../../profiles"; - -/** - * Optional parameters to profile manager load all profiles - * @export - * @interface ICliLoadAllProfiles - * @extends ILoadAllProfiles - */ -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface ICliLoadAllProfiles extends ILoadAllProfiles {} diff --git a/packages/imperative/src/cmd/src/doc/profiles/parms/ICliLoadProfile.ts b/packages/imperative/src/cmd/src/doc/profiles/parms/ICliLoadProfile.ts deleted file mode 100644 index ac1a6ba0e9..0000000000 --- a/packages/imperative/src/cmd/src/doc/profiles/parms/ICliLoadProfile.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ILoadProfile } from "../../../../../profiles"; - -/** - * Profile Manager "loadProfile" input parameters. Indicates which profile to load (named or default) and if - * not finding the profile should be considered and error, etc. - * @export - * @interface ICliLoadProfile - * @extends ILoadProfile - */ -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface ICliLoadProfile extends ILoadProfile {} diff --git a/packages/imperative/src/cmd/src/doc/profiles/parms/ICommandLoadProfile.ts b/packages/imperative/src/cmd/src/doc/profiles/parms/ICommandLoadProfile.ts deleted file mode 100644 index dffa08aff2..0000000000 --- a/packages/imperative/src/cmd/src/doc/profiles/parms/ICommandLoadProfile.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -/** - * Command profile loader internal parameters. Indicates the profile to be loaded (by name) and - * other options/control parameters. - * @export - * @interface ICommandLoadProfile - */ -export interface ICommandLoadProfile { - /** - * The type of the profile to load. - * @type {string} - * @memberof ICommandLoadProfile - */ - type: string; - /** - * The name of the profile to load for the type specified. - * @type {string} - * @memberof ICommandLoadProfile - */ - name: string; - /** - * Indicates that the user specifically named this profile to be loaded (not a default, etc.) - * @type {boolean} - * @memberof ICommandLoadProfile - */ - userSpecified: boolean; - /** - * Load the default profile for the group. If this option is specified, name is ignored. - * @type {boolean} - * @memberof ICommandLoadProfile - */ - loadDefault: boolean; - /** - * Indicates that a failure to load this profile is not a problem. - * @type {boolean} - * @memberof ICommandLoadProfile - */ - optional: boolean; -} diff --git a/packages/imperative/src/cmd/src/doc/profiles/parms/ICommandProfileLoaderParms.ts b/packages/imperative/src/cmd/src/doc/profiles/parms/ICommandProfileLoaderParms.ts index b0a22d2dad..35837a8abb 100644 --- a/packages/imperative/src/cmd/src/doc/profiles/parms/ICommandProfileLoaderParms.ts +++ b/packages/imperative/src/cmd/src/doc/profiles/parms/ICommandProfileLoaderParms.ts @@ -9,10 +9,8 @@ * */ -import { IProfileManagerFactory } from "../../../../../profiles"; import { Logger } from "../../../../../logger"; import { ICommandDefinition } from "../../ICommandDefinition"; -import { ICommandProfileTypeConfiguration } from "../definition/ICommandProfileTypeConfiguration"; /** * Control parameters for the command profile loader. * @export @@ -25,13 +23,6 @@ export interface ICommandProfileLoaderParms { * @memberof ICommandProfileLoaderParms */ commandDefinition: ICommandDefinition; - /** - * The profile Manager factory to create profile manager instances depending on the profile types required - * by the command. - * @type {IProfileManagerFactory} - * @memberof ICommandProfileLoaderParms - */ - profileManagerFactory: IProfileManagerFactory; /** * Optional logger instance - if not supplied, then Logger.getImperativeLogger() is used. * @type {Logger} diff --git a/packages/imperative/src/cmd/src/doc/response/response/ICommandPrepared.ts b/packages/imperative/src/cmd/src/doc/response/response/ICommandPrepared.ts deleted file mode 100644 index 636e0fbc58..0000000000 --- a/packages/imperative/src/cmd/src/doc/response/response/ICommandPrepared.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { CommandProfiles } from "../../../../src/profiles/CommandProfiles"; -import { ICommandArguments } from "../../../../src/doc/args/ICommandArguments"; -/** - * Command Processor prepare response. - * @export - * @interface ICommandPrepared - */ -export interface ICommandPrepared { - /** - * The profile map object for all profiles loaded for commands. - * @type {CommandProfiles} - * @memberof ICommandPrepared - */ - profiles: CommandProfiles; - /** - * Imperative arguments object. Starts with arguments passed parsed by - * Yargs as a base and fills in the rest from ENV/profile/defaults. - * Eventually passed to handlers. - * @type {ICommandArguments} - */ - args: ICommandArguments; -} diff --git a/packages/imperative/src/cmd/src/handlers/FailedCommandHandler.ts b/packages/imperative/src/cmd/src/handlers/FailedCommandHandler.ts index 2e9d7c4e7b..2aa939681b 100644 --- a/packages/imperative/src/cmd/src/handlers/FailedCommandHandler.ts +++ b/packages/imperative/src/cmd/src/handlers/FailedCommandHandler.ts @@ -23,7 +23,7 @@ export default class FailedCommandHandler implements ICommandHandler { params.response.console.error(params.arguments.error.stack); } const additionalDetails: string = params.arguments.error ? params.arguments.error.message : undefined; - const msg: string = (additionalDetails == null) ? params.arguments.failureMessage : additionalDetails + "\n" + const msg: string = additionalDetails == null ? params.arguments.failureMessage : additionalDetails + "\n" + params.arguments.failureMessage; const failedCommandError: IImperativeError = { msg, diff --git a/packages/imperative/src/cmd/src/help/DefaultHelpGenerator.ts b/packages/imperative/src/cmd/src/help/DefaultHelpGenerator.ts index 7152110297..59387adb23 100644 --- a/packages/imperative/src/cmd/src/help/DefaultHelpGenerator.ts +++ b/packages/imperative/src/cmd/src/help/DefaultHelpGenerator.ts @@ -19,6 +19,7 @@ import { IHelpGeneratorParms } from "./doc/IHelpGeneratorParms"; import { IHelpGeneratorFactoryParms } from "./doc/IHelpGeneratorFactoryParms"; import { compareCommands, ICommandDefinition } from "../../src/doc/ICommandDefinition"; import stripAnsi = require("strip-ansi"); +import { CliUtils } from "../../../utilities/src/CliUtils"; /** * Imperative default help generator. Accepts the command definitions and constructs @@ -133,7 +134,7 @@ export class DefaultHelpGenerator extends AbstractHelpGenerator { if (!this.mProduceMarkdown && this.mCommandDefinition.name != null && this.mCommandDefinition.name.length > 0) { helpText += "\n" + this.buildHeader("COMMAND NAME"); - helpText += (DefaultHelpGenerator.HELP_INDENT + this.mCommandDefinition.name); + helpText += DefaultHelpGenerator.HELP_INDENT + this.mCommandDefinition.name; if (this.mCommandDefinition.aliases != null && this.mCommandDefinition.aliases.length > 0) { helpText += " | " + this.mCommandDefinition.aliases.join(" | "); } @@ -270,7 +271,7 @@ export class DefaultHelpGenerator extends AbstractHelpGenerator { // Place the positional parameters. if (this.mCommandDefinition.positionals != null) { for (const positional of this.mCommandDefinition.positionals) { - usage += " " + ((positional.required) ? "<" + positional.name + ">" : "[" + positional.name + "]"); + usage += " " + (positional.required ? "<" + positional.name + ">" : "[" + positional.name + "]"); } } // Append the options segment @@ -355,25 +356,12 @@ export class DefaultHelpGenerator extends AbstractHelpGenerator { if (!this.mProduceMarkdown) { descriptionForHelp += this.buildHeader("DESCRIPTION"); } - let description = this.mCommandDefinition.description - || this.mCommandDefinition.summary; - - // we place the deprecated message in the DESCRIPTION help section - if (this.mCommandDefinition.deprecatedReplacement != null) { - const noNewlineInText = this.mCommandDefinition.deprecatedReplacement.replace(/\n/g, " "); - description += this.grey("\n\nWarning: This " + this.mCommandDefinition.type + - " has been deprecated.\n"); - if(this.mCommandDefinition.deprecatedReplacement === "") - { - description += this.grey("Obsolete component. No replacement exists"); - } - else - { - description += this.grey("Recommended replacement: " + noNewlineInText); - } - } + let description = this.mCommandDefinition.description || this.mCommandDefinition.summary; + // Use consolidated deprecated message logic + description += + this.grey(CliUtils.generateDeprecatedMessage(this.mCommandDefinition, true)); if (this.mProduceMarkdown) { - description = this.escapeMarkdown(description); // escape Markdown special characters + description = this.escapeMarkdown(description); } if (this.skipTextWrap) { descriptionForHelp += TextUtils.indentLines(description, this.mProduceMarkdown ? "" : DefaultHelpGenerator.HELP_INDENT); @@ -401,9 +389,9 @@ export class DefaultHelpGenerator extends AbstractHelpGenerator { this.dimGrey("{{italic}}(" + this.explainType(positional.type) + "){{italic}}"); let fullDescription = positional.description; if (positional.regex) { - fullDescription += (DefaultHelpGenerator.HELP_INDENT + + fullDescription += DefaultHelpGenerator.HELP_INDENT + DefaultHelpGenerator.HELP_INDENT + "Must match regular expression: {{codeBegin}}" - + positional.regex + "{{codeEnd}}\n\n"); + + positional.regex + "{{codeEnd}}\n\n"; } positionalsHelpText += this.buildOptionText(positionalString, fullDescription); } @@ -509,7 +497,7 @@ export class DefaultHelpGenerator extends AbstractHelpGenerator { examplesText = this.mCommandDefinition.examples.map((example) => { const prefix = example.prefix != null ? example.prefix + "{{space}} " : ""; const exampleHyphen = this.mProduceMarkdown ? "" : "-"; - const options = (example.options.length > 0) ? ` ${example.options}` : ""; + const options = example.options.length > 0 ? ` ${example.options}` : ""; const description = this.mProduceMarkdown ? this.escapeMarkdown(example.description) : example.description; let exampleText = "{{bullet}}" + exampleHyphen + " {{space}}" + description + ":\n\n"; if (this.skipTextWrap) { diff --git a/packages/imperative/src/cmd/src/help/WebHelpGenerator.ts b/packages/imperative/src/cmd/src/help/WebHelpGenerator.ts index f040a9a7e4..70fffe64d0 100644 --- a/packages/imperative/src/cmd/src/help/WebHelpGenerator.ts +++ b/packages/imperative/src/cmd/src/help/WebHelpGenerator.ts @@ -160,7 +160,7 @@ export class WebHelpGenerator { { commandDefinition: uniqueDefinitions, fullCommandTree: uniqueDefinitions, skipTextWrap: true }); rootHelpContent += this.renderMarkdown(this.buildChildrenSummaryTables(helpGen, rootCommandName) + "\n\n" + helpGen.buildCommandOptionsSection() + helpGen.buildGlobalOptionsSection()); - this.singlePageHtml = rootHelpContent.replace(/

Groups.+?<\/ul>/s, ""); + this.singlePageHtml = rootHelpContent.replace(/

Groups[^]+?<\/ul>/, ""); rootHelpContent += this.genDocsFooter(); fs.writeFileSync(rootHelpHtmlPath, rootHelpContent); cmdResponse.console.log(Buffer.from(".")); @@ -291,7 +291,7 @@ export class WebHelpGenerator { } // Generate HTML anchor in front of header - const anchorText = ``; + const anchorText = ``; if (definition.type === "group") { // Remove sections from HTML that would be redundant @@ -349,7 +349,7 @@ export class WebHelpGenerator { id: helpHtmlFile, text: [definition.name, ...definition.aliases].join(" | ") }; - parentNode.children = [...(parentNode.children || []), childNode]; + parentNode.children = [...parentNode.children || [], childNode]; definition.aliases.forEach((alias: string) => { if (alias !== definition.name) { diff --git a/packages/imperative/src/cmd/src/help/WebHelpManager.ts b/packages/imperative/src/cmd/src/help/WebHelpManager.ts index 6e5a431505..161b0959b2 100644 --- a/packages/imperative/src/cmd/src/help/WebHelpManager.ts +++ b/packages/imperative/src/cmd/src/help/WebHelpManager.ts @@ -101,7 +101,7 @@ export class WebHelpManager implements IWebHelpManager { const newMetadata: MaybePackageMetadata = this.checkIfMetadataChanged(); if (newMetadata !== null) { - (new WebHelpGenerator(this.mFullCommandTree, ImperativeConfig.instance, this.webHelpDir)). + new WebHelpGenerator(this.mFullCommandTree, ImperativeConfig.instance, this.webHelpDir). buildHelp(cmdResponse); this.writePackageMetadata(newMetadata); } @@ -121,7 +121,7 @@ export class WebHelpManager implements IWebHelpManager { } try { - const htmlFile = (inContext != null) ? "launcher.html" : "index.html"; + const htmlFile = inContext != null ? "launcher.html" : "index.html"; ProcessUtils.openInDefaultApp(`file:///${this.webHelpDir}/${htmlFile}`); } catch (e) { throw new ImperativeError({ diff --git a/packages/imperative/src/cmd/src/help/abstract/AbstractHelpGenerator.ts b/packages/imperative/src/cmd/src/help/abstract/AbstractHelpGenerator.ts index f3ca75bf57..90aad23474 100644 --- a/packages/imperative/src/cmd/src/help/abstract/AbstractHelpGenerator.ts +++ b/packages/imperative/src/cmd/src/help/abstract/AbstractHelpGenerator.ts @@ -125,7 +125,7 @@ export abstract class AbstractHelpGenerator implements IHelpGenerator { public getOptionAndAliasesString(option: ICommandOptionDefinition, caseSensitive?: boolean): string { let aliasString = ""; if (!(option.aliases == null) && option.aliases.length > 0 && - (option.aliases.join("").trim().length !== 0)) { + option.aliases.join("").trim().length !== 0) { const formattedOptAliases = []; aliasString += " | "; diff --git a/packages/imperative/src/cmd/src/profiles/CliProfileManager.ts b/packages/imperative/src/cmd/src/profiles/CliProfileManager.ts deleted file mode 100644 index a4aa983665..0000000000 --- a/packages/imperative/src/cmd/src/profiles/CliProfileManager.ts +++ /dev/null @@ -1,694 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { - BasicProfileManager, - IProfile, - IProfileManager, - IProfileSaved, - IProfileUpdated, - IProfileValidated, - ISaveProfileFromCliArgs, - IUpdateProfileFromCliArgs, - IValidateProfileForCLI, - ProfilesConstants, - ProfileUtils -} from "../../../profiles"; -import { inspect } from "util"; -import { ImperativeError } from "../../../error"; -import { Arguments } from "yargs"; -import { CommandResponse } from "../response/CommandResponse"; -import { ICommandHandlerRequire } from "../doc/handler/ICommandHandlerRequire"; -import { ICommandHandler } from "../../src/doc/handler/ICommandHandler"; -import { ICommandProfileTypeConfiguration } from "../doc/profiles/definition/ICommandProfileTypeConfiguration"; -import { CommandProfiles } from "./CommandProfiles"; -import { ICommandProfileProperty } from "../doc/profiles/definition/ICommandProfileProperty"; -import { CredentialManagerFactory } from "../../../security"; -import { IDeleteProfile, IProfileDeleted, IProfileLoaded } from "../../../profiles/src/doc"; -import { SecureOperationFunction } from "../types/SecureOperationFunction"; -import { ICliLoadProfile } from "../doc/profiles/parms/ICliLoadProfile"; -import { ICliLoadAllProfiles } from "../doc/profiles/parms/ICliLoadAllProfiles"; -import { CliUtils } from "../../../utilities/src/CliUtils"; - -/** - * A profile management API compatible with transforming command line arguments into - * profiles - */ -export class CliProfileManager extends BasicProfileManager { - - /** - * NOTE: This is just a copy of BasicProfileManager.loadAll - * REASON: We needed the Abstract profile manager to call the CLI profile manager to handle loading of secure properties - * Loads all profiles from every type. Profile types are determined by reading all directories within the - * profile root directory. - * @returns {Promise} - The list of all profiles for every type - */ - public async loadAll(params?: ICliLoadAllProfiles): Promise { - this.log.trace(`Loading all profiles for type "${this.profileType}"...`); - // Load all the other profiles for other types - const loadAllProfiles: any[] = []; - - // Load only the profiles for the type if requested - if (params != null && params.typeOnly) { - const names: string[] = this.getAllProfileNames(); - for (const name of names) { - loadAllProfiles.push(this.load({ - name, - failNotFound: true, - loadDependencies: false, - noSecure: params.noSecure - })); - } - } else { - - // Otherwise, load all profiles of all types - for (const typeConfig of this.profileTypeConfigurations) { - const typeProfileManager = new CliProfileManager({ - profileRootDirectory: this.profileRootDirectory, - typeConfigurations: this.profileTypeConfigurations, - type: typeConfig.type, - logger: this.log, - loadCounter: this.loadCounter - }); - - // Get all the profile names for the type and attempt to load every one - const names: string[] = typeProfileManager.getAllProfileNames(); - for (const name of names) { - this.log.debug(`Loading profile "${name}" of type "${typeConfig.type}".`); - loadAllProfiles.push(typeProfileManager.load({ - name, - failNotFound: true, - loadDependencies: false, - noSecure: (params != null) ? params.noSecure : undefined - })); - } - } - } - - // Construct the full list for return - let allProfiles: IProfileLoaded[] = []; - try { - this.log.trace(`Awaiting all loads...`); - const theirProfiles = await Promise.all(loadAllProfiles); - for (const theirs of theirProfiles) { - allProfiles = allProfiles.concat(theirs); - } - this.log.trace(`All loads complete.`); - } catch (e) { - this.log.error(e.message); - throw new ImperativeError({msg: e.message, additionalDetails: e.additionalDetails, causeErrors: e}); - } - - return allProfiles; - } - - /** - * Overridden saveProfile functionality. - * If CLI args are provided, profile fields are built from the args. - * Otherwise BaseProfileManager functionality is used. - * @param {ISaveProfileFromCliArgs} parms - parameters for the save, potentially including CLI args - * @returns {Promise} - promise which fulfills with the save results - */ - protected async saveProfile(parms: ISaveProfileFromCliArgs): Promise { - // If the arguments are present, build the new profile from the arguments - // Otherwise, just save the profile passed. - this.log.trace("Cli save profile entered"); - const validationParms: IValidateProfileForCLI = JSON.parse(JSON.stringify(parms)); - validationParms.readyForValidation = true; - - if (parms.args != null) { - this.log.trace(`Arguments supplied, constructing profile from arguments:\n${inspect(parms.args, {depth: null})}`); - parms.profile = await this.createProfileFromCommandArguments(parms.args, parms.profile); - - validationParms.profile = parms.profile; - delete parms.args; - this.log.debug(`Validating profile build (name: ${parms.name}).`); - await this.validate(validationParms); // validate now that the profile has been built - } else { - // profile should already be ready - this.log.trace("No arguments specified, performing the basic validation (schema, etc.)."); - await this.validate(validationParms); - } - parms.profile = await this.processSecureProperties(parms.name, parms.profile); - return super.saveProfile(parms); - } - - /** - * Overridden updateProfile functionality - * If CLI args are provided, profile fields are built from the arguments. Otherwise - * the BaseProfileManager update functionality is used - * - * @param {IUpdateProfileFromCliArgs} parms - parameters, potentially including CLI args - * @returns {Promise} - promise which contains the updated profile, path, and message - * when fulfilled - */ - protected async updateProfile(parms: IUpdateProfileFromCliArgs): Promise { - // If there are arguments present, then it is assumed that we want to update from the args, - // otherwise we will invoke the default updateProfile which assumes that the profile update - // has already been constructed and just needs to be saved. - // When updating from the args, we do not need to run validation twice when saving the profile - let updated: any; - if (parms.args != null) { - const newManagerParams: IProfileManager = JSON.parse(JSON.stringify(this.managerParameters)); - newManagerParams.loadCounter = this.loadCounter; - newManagerParams.logger = this.log; - const loadedProfile = await new CliProfileManager(newManagerParams).loadProfile({name: parms.name}); - updated = await this.updateProfileFromCliArgs(parms, loadedProfile.profile, - (parms.profile == null) ? {} : parms.profile); - delete parms.args; - this.log.debug("Profile \"%s\" of type \"%s\" has been updated from CLI arguments. " + - "Validating the structure of the profile.", parms.name, this.profileType); - } else { - updated = await super.updateProfile(parms); - this.log.debug("No CLI args were provided. Used the BasicProfileManager update API"); - - const validationParms: IValidateProfileForCLI = JSON.parse(JSON.stringify(parms)); - validationParms.readyForValidation = true; - validationParms.profile = updated.profile; - await this.validateProfile(validationParms); - } - - return updated; - } - - /** - * Overridden loadProfile functionality - * After the BasicProfileManager loads the profile, we process the secured properties for the CLi to use - * - * @param {ICliLoadProfile} parms - Load control params - see the interface for full details - * @returns {Promise} - Promise that is fulfilled when complete (or rejected with an Imperative Error) - */ - protected async loadProfile(parms: ICliLoadProfile): Promise { - const loadedProfile = await super.loadProfile(parms); - const profile = loadedProfile.profile; - - // If noSecure is specified, skip secure loading - let securelyLoadValue: SecureOperationFunction; - if (!parms.noSecure && CredentialManagerFactory.initialized) { - /** - * Securely load a property associated with a given profile - * @param {string} propertyNamePath - The path to the property - * @return {Promise} - */ - securelyLoadValue = async (propertyNamePath: string, _: any, optional?: boolean): Promise => { - let ret; - try { - this.log.debug( - `Loading secured field with key ${propertyNamePath} for profile` + - ` ("${parms.name}" of type "${this.profileType}").` - ); - // Use the Credential Manager to store the credentials - ret = await CredentialManagerFactory.manager.load( - ProfileUtils.getProfilePropertyKey(this.profileType, parms.name, propertyNamePath), - optional - ); - } catch (err) { - this.log.error( - `Unable to load secure field "${propertyNamePath}" ` + - `associated with profile "${parms.name}" of type "${this.profileType}".` - ); - - let additionalDetails: string = err.message + (err.additionalDetails ? `\n${err.additionalDetails}` : ""); - additionalDetails = this.addProfileInstruction(additionalDetails); - - this.log.error(`Error: ${additionalDetails}`); - if (err.causeErrors != null) { - this.log.error("Cause errors: " + inspect(err.causeErrors)); - } - throw new ImperativeError({ - msg: `Unable to load the secure field "${propertyNamePath}" associated with ` + - `the profile "${parms.name}" of type "${this.profileType}".`, - additionalDetails, - causeErrors: err - }); - } - - return (ret != null) ? JSON.parse(ret) : undefined; // Parse it after loading it. We stringify-ed before saving it - }; - } - - if (profile != null) { - for (const prop of Object.keys(this.profileTypeConfiguration.schema.properties)) { - profile[prop] = await this.findOptions(this.profileTypeConfiguration.schema.properties[prop], prop, profile[prop], securelyLoadValue); - } - } - - // Return the loaded profile - loadedProfile.profile = profile || {}; - return loadedProfile; - } - - /** - * Overridden loadProfile functionality - * Before the BasicProfileManager deletes the profile, we remove the secure properties associated with the profile - * - * @param {IDeleteProfile} parms - Delete control params - see the interface for full details - * @returns {Promise} - Promise that is fulfilled when complete (or rejected with an Imperative Error) - */ - protected async deleteProfile(parms: IDeleteProfile): Promise { - - // If the credential manager is null, we are using plain text - let deleteSecureProperty: SecureOperationFunction; - if (CredentialManagerFactory.initialized) { - /** - * Delete a secure property associated with a given profile - * @param {string} propertyNamePath - The path to the property - * @return {Promise} - */ - deleteSecureProperty = async (propertyNamePath: string): Promise => { - try { - this.log - .debug(`Deleting secured field with key ${propertyNamePath} for profile ("${parms.name}" of type "${this.profileType}").`); - // Use the Credential Manager to store the credentials - await CredentialManagerFactory.manager.delete( - ProfileUtils.getProfilePropertyKey(this.profileType, parms.name, propertyNamePath) - ); - } catch (err) { - this.log.error(`Unable to delete secure field "${propertyNamePath}" ` + - `associated with profile "${parms.name}" of type "${this.profileType}".`); - - let additionalDetails: string = err.message + (err.additionalDetails ? `\n${err.additionalDetails}` : ""); - additionalDetails = this.addProfileInstruction(additionalDetails); - this.log.error(`Error: ${additionalDetails}`); - - throw new ImperativeError({ - msg: `Unable to delete the secure field "${propertyNamePath}" associated with ` + - `the profile "${parms.name}" of type "${this.profileType}".`, - additionalDetails, - causeErrors: err - }); - } - }; - } - - for (const prop of Object.keys(this.profileTypeConfiguration.schema.properties)) { - await this.findOptions(this.profileTypeConfiguration.schema.properties[prop], prop, null, deleteSecureProperty); - } - - return super.deleteProfile(parms); - } - - /** - * Validate a profile's structure, skipping the validation if we haven't built the - * profile's fields from the CLI arguments yet. - * @param {IValidateProfileForCLI} parms - validate profile parameters. if these don't - * have readyForValidation = true, validation is - * skipped - * @returns {Promise} - */ - protected async validateProfile(parms: IValidateProfileForCLI): Promise { - if (parms.readyForValidation) { - this.log.debug(`Invoking the basic profile manager validate for profile: "${parms.name}"`); - return super.validateProfile(parms); - } else { - this.log.trace(`Skipping the validate for profile (as it's being built): "${parms.name}"`); - return {message: "Skipping validation until profile is built"}; - } - } - - /** - * After the DefaultCredentialManager reports an error resolution of recreating - * a credential, add instruction to recreate the profile. - * - * @param {String} errDetails - The additional details of an error thrown - * by DefaultCredentialManager. - * - * @returns {string} An error details string that contains an instruction to - * recreate the profile (when appropriate). - */ - private addProfileInstruction(errDetails: string): string { - const recreateCredText: string = "Recreate the credentials in the vault"; - const recreateProfileText: string = - " To recreate credentials, issue a 'profiles create' sub-command with the --ow flag.\n"; - if (errDetails.includes(recreateCredText)) { - errDetails += recreateProfileText; - } else { - const additionalDetails = CredentialManagerFactory.manager.secureErrorDetails(); - if (additionalDetails != null) { - errDetails += "\n\n" + additionalDetails; - } - } - return errDetails; - } - - /** - * Helper routine to find nested properties - * Inspired by the inner function of insertCliArgumentsIntoProfile - * - * @param {ICommandProfileProperty} prop - profile property - * @param {string} propNamePath - Dot notation path of a property (e.g. my.nested.property) - * @param {*} propValue - Current value of the property while traversing down the object tree - * @param {SecureOperationFunction} secureOp - Function to be executed if we are supposed to process secure properties - * @returns {Promise} Processed version of a property - */ - private async findOptions(prop: ICommandProfileProperty, propNamePath: string, propValue: any, secureOp?: SecureOperationFunction): Promise { - if (prop.optionDefinition != null) { - // once we reach a property with an option definition, - // we now have the complete path to the property - // so we will set the value on the property from the profile - const optionName = prop.optionDefinition.name; - this.log.debug("Setting profile field %s from command line option %s", propNamePath, optionName); - if (secureOp && prop.secure) { - this.log.debug("Performing secure operation on property %s", propNamePath); - return secureOp(propNamePath, propValue, !prop.optionDefinition.required); - } - return Promise.resolve(propValue); - } - if (prop.properties != null) { - if (secureOp && prop.secure) { - if (!propValue || Object.keys(propValue).length === 0) { // prevents from performing operations on empty objects - return Promise.resolve(null); - } - - this.log.debug("Performing secure operation on property %s", propNamePath); - return secureOp(propNamePath, propValue); - } - const tempProperties: any = {}; - for (const childPropertyName of Object.keys(prop.properties)) { - tempProperties[childPropertyName] = - await this.findOptions( - prop.properties[childPropertyName], - propNamePath + "." + childPropertyName, - ((propValue != null) && (propValue[childPropertyName] != null)) ? - JSON.parse(JSON.stringify(propValue[childPropertyName])) : null, - secureOp - ); - } - return Promise.resolve(tempProperties); - } - - return Promise.resolve(propValue); - } - - /** - * Process and store all secure properties and replace them with a constant for display purposes - * @param name - the name of the profile with which the secure properties are associated - * @param {IProfile} profile - Profile contents to be processed - * @return {Promise} - */ - private async processSecureProperties(name: string, profile: IProfile): Promise { - // If the credential manager is null, skip secure props and the profile will default to plain text - let securelyStoreValue: SecureOperationFunction; - if (CredentialManagerFactory.initialized) { - /** - * Securely store a property associated with a given profile - * @param {string} propertyNamePath - The path to the property - * @param {string} propertyValue - The value associated with the given profile property - * @return {Promise} - */ - securelyStoreValue = async (propertyNamePath: string, propertyValue: string): Promise => { - if (propertyValue == null) { - // don't store null values but still remove value that may have been stored previously - this.log.debug(`Deleting secured field with key ${propertyNamePath}` + - ` for profile (of type "${this.profileType}").`); - - // In this particular case, do not throw an error if delete doesn't work. - try { - await CredentialManagerFactory.manager.delete( - ProfileUtils.getProfilePropertyKey(this.profileType, name, propertyNamePath) - ); - } catch (err) { - // If delete did not work here, it is probably okay. - } - - return undefined; - } - try { - this.log.debug(`Associating secured field with key ${propertyNamePath}` + - ` for profile (of type "${this.profileType}").`); - // Use the Credential Manager to store the credentials - await CredentialManagerFactory.manager.save( - ProfileUtils.getProfilePropertyKey(this.profileType, name, propertyNamePath), - JSON.stringify(propertyValue) // Stringify it before saving it. We will parse after loading it - ); - } catch (err) { - this.log.error(`Unable to store secure field "${propertyNamePath}" ` + - `associated with profile "${name}" of type "${this.profileType}".`); - - let additionalDetails: string = err.message + (err.additionalDetails ? `\n${err.additionalDetails}` : ""); - additionalDetails = this.addProfileInstruction(additionalDetails); - this.log.error(`Error: ${additionalDetails}`); - - throw new ImperativeError({ - msg: `Unable to store the secure field "${propertyNamePath}" associated with ` + - `the profile "${name}" of type "${this.profileType}".`, - additionalDetails, - causeErrors: err - }); - } - - // The text in the profile will read "managed by " - return `${ProfilesConstants.PROFILES_OPTION_SECURELY_STORED} ${CredentialManagerFactory.manager.name}`; - }; - } - - for (const prop of Object.keys(this.profileTypeConfiguration.schema.properties)) { - profile[prop] = await this.findOptions(this.profileTypeConfiguration.schema.properties[prop], prop, profile[prop], securelyStoreValue); - } - - return profile; - } - - /** - * Update an existing profile with arguments from the user based on - * the schema and configuration for this profile type - * @param {IUpdateProfileFromCliArgs} parms - parameters including args - * @param {IProfile} oldProfile - the pre-existing profile to update - * @param {IProfile} newProfile - new profile which will have fields set from CLI args - * @returns {Promise} promise which provides the finished profile on fulfill - */ - private async updateProfileFromCliArgs(parms: IUpdateProfileFromCliArgs, oldProfile: IProfile, newProfile: IProfile): Promise { - // Create the modified profile from the CLI arguments - const updatedProfile = await this.updateProfileFieldsFromCommandArguments(oldProfile, newProfile, parms.args, parms.merge); - // Save the profile (basically just overwrites the old profile) - let createResponse: IProfileSaved; - try { - this.log.info("Saving updated profile \"%s\" of type \"%s\"", - parms.name, this.profileType); - createResponse = await this.saveProfile({ - name: parms.name, - type: this.profileType, - profile: updatedProfile, - updateDefault: false, - overwrite: true, - }); - } catch (saveErr) { - throw new ImperativeError({ - msg: `An error occurred while saving the modified profile ` + - `("${parms.name}" of type "${this.profileType}"): ${saveErr.message}` - }); - } - - // Return the success response - return { - profile: updatedProfile, - path: createResponse.path, - message: `Profile "${parms.name}" of type "${this.profileType}" successfully updated from command line arguments.` - }; - } - - /** - * - * If a custom handler is provided for update, the handler will be loaded and invoked - * in order to build the finished profile - * @param {IProfile} oldProfile - the old profile to update - * @param newProfile - new profile which may have fields populated, which will be updated from the CLI args - * @param {yargs.Arguments} newArguments - CLi arguments specified by the user - * @param merge - should the profiles be merged? (will be skipped if there is a custom update profile handler) - * @returns {Promise} - promise which provides the finished profile on fulfill - */ - private async updateProfileFieldsFromCommandArguments(oldProfile: IProfile, newProfile: IProfile, newArguments: Arguments, - merge: boolean): Promise { - const profileConfig = this.profileTypeConfiguration; - if (profileConfig.updateProfileFromArgumentsHandler != null) { - // if there is a custom update profile handler, they can call mergeProfile - // from their handler, so we will not do it for them to avoid issues - this.log.debug("Loading custom update profile handler: " + profileConfig.updateProfileFromArgumentsHandler); - const response = new CommandResponse({silent: true}); - let handler: ICommandHandler; - try { - const commandHandler: ICommandHandlerRequire = require(profileConfig.updateProfileFromArgumentsHandler); - handler = new commandHandler.default(); - } catch (e) { - const errorMessage = this.log.error(`Error encountered loading custom update profile handler ` + - `${profileConfig.updateProfileFromArgumentsHandler}:\n` + +e.message); - throw new ImperativeError( - { - msg: errorMessage, - causeErrors: [e], - stack: e.stack - }); - } - try { - await handler.process({ - arguments: CliUtils.buildBaseArgs(newArguments), - positionals: newArguments._, - response, - fullDefinition: undefined, - definition: undefined, - profiles: new CommandProfiles(new Map()), - stdin: process.stdin - }); - } catch (invokeErr) { - const errorMessage = this.log.error(`Error encountered updating profile of type ${this.profileType} ` + - ` with custom update profile handler ` + - `("${profileConfig.updateProfileFromArgumentsHandler}"):` + - invokeErr.message); - throw new ImperativeError( - { - msg: errorMessage, - causeErrors: [invokeErr], - stack: invokeErr.stack - }); - } - - // zeroth response object is specified to be - // the finalized profile - const finishedProfile = response.buildJsonResponse().data; - this.insertDependenciesIntoProfileFromCLIArguments(newArguments, finishedProfile); - return finishedProfile; - } else { - this.log.debug("No custom update profile handler was specified. Building profile from CLI arguments"); - await this.insertCliArgumentsIntoProfile(newArguments, newProfile); - if (merge) { - this.log.debug("Merging new profile created from CLI arguments with existing profile"); - newProfile = this.mergeProfiles(oldProfile, newProfile); - } - return newProfile; - } - } - - /** - * Take command line arguments from the user and create a profile from them using the schema and configuration for - * the profile type - * @param {yargs.Arguments} profileArguments - CLI arguments specified by the user - * @param {IProfile} starterProfile - the profile with name and type to use to start the profile creation - * @returns {Promise} profile which provides the finished profile on fulfill - */ - private async createProfileFromCommandArguments(profileArguments: Arguments, starterProfile: IProfile): Promise { - const profileConfig = this.profileTypeConfiguration; - if (profileConfig.createProfileFromArgumentsHandler != null) { - const response = new CommandResponse({silent: true, args: profileArguments}); - let handler: ICommandHandler; - try { - const commandHandler: ICommandHandlerRequire = require(profileConfig.createProfileFromArgumentsHandler); - handler = new commandHandler.default(); - } catch (e) { - const errorMessage = this.log.error(`Error encountered loading custom create profile handler ` + - `${profileConfig.createProfileFromArgumentsHandler}:\n` + +e.message); - throw new ImperativeError( - { - msg: errorMessage, - causeErrors: [e], - stack: e.stack - }); - } - try { - await handler.process({ - arguments: CliUtils.buildBaseArgs(profileArguments), - positionals: profileArguments._, - response, - fullDefinition: undefined, - definition: undefined, - profiles: new CommandProfiles(new Map()), - stdin: process.stdin - }); - } catch (invokeErr) { - const errorMessage = this.log.error("Error encountered building new profile with custom create profile handler:" + invokeErr.message); - throw new ImperativeError( - { - msg: errorMessage, - causeErrors: [invokeErr], - stack: invokeErr.stack - }); - } - - // zeroth response object is specified to be - // the finalized profile - const finishedProfile = response.buildJsonResponse().data; - this.insertDependenciesIntoProfileFromCLIArguments(profileArguments, finishedProfile); - - return finishedProfile; - } else { - const profile: IProfile = {}; - // default case - no custom handler - // build profile object directly from command arguments - await this.insertCliArgumentsIntoProfile(profileArguments, profile); - this.insertDependenciesIntoProfileFromCLIArguments(profileArguments, profile); - return profile; - } - } - - /** - * Default style of building of profile fields to option definitions defined in the schema - * Will only work if there is a one-to-one option definition mapping for schema fields - * @param {yargs.Arguments} args - the arguments specified by the user - * @param {IProfile} profile - the profile so far, which will be updated - */ - private async insertCliArgumentsIntoProfile(args: Arguments, profile: IProfile): Promise { - /** - * Helper routine to find nested properties - * @param {Object} property - profile property - * @param {ICommandProfileProperty} property - profile property - * @param {string} propertyNamePath - Dot notation path of a property (e.g. my.nested.property) - */ - const findOptions = async (property: ICommandProfileProperty, propertyNamePath: string): Promise => { - if (property.optionDefinition != null) { - // once we reach a property with an option definition, - // we now have the complete path to the property - // so we will set the value on the property from the profile - this.log.debug("Setting profile field %s from command line option %s", propertyNamePath, property.optionDefinition.name); - return args[property.optionDefinition.name]; - } - - if (property.properties != null) { - const tempProperties: any = {}; - for (const childPropertyName of Object.keys(property.properties)) { - tempProperties[childPropertyName] = - await findOptions(property.properties[childPropertyName], propertyNamePath + "." + childPropertyName); - } - return tempProperties; - } - - // Don't define any value here if the profile field cannot be set by a CLI option - return undefined; - }; - - for (const propertyName of Object.keys(this.profileTypeConfiguration.schema.properties)) { - profile[propertyName] = - await findOptions(this.profileTypeConfiguration.schema.properties[propertyName], propertyName); - } - } - - /** - * Build the "dependencies" field of a profile object from command line arguments - * @param {yargs.Arguments} args - the command line arguments from the user - * @param {IProfile} profile - the profile object so far. - */ - private insertDependenciesIntoProfileFromCLIArguments(args: Arguments, profile: IProfile): void { - if (this.profileTypeConfiguration.dependencies != null) { - const dependencies: Array<{ type: string, name: string }> = []; - for (const dependency of this.profileTypeConfiguration.dependencies) { - const optionName = ProfileUtils.getProfileOption(dependency.type); - if (args[optionName] != null) { - const dependentProfileName = args[optionName]; - this.log.debug("Inserting dependency profile named \"%s\" of type \"%s\"", dependentProfileName, dependency.type); - dependencies.push({ - type: dependency.type, - name: dependentProfileName as string - }); - } - } - profile.dependencies = dependencies; - } - } - -} diff --git a/packages/imperative/src/cmd/src/profiles/CommandProfileLoader.ts b/packages/imperative/src/cmd/src/profiles/CommandProfileLoader.ts deleted file mode 100644 index df0aee3220..0000000000 --- a/packages/imperative/src/cmd/src/profiles/CommandProfileLoader.ts +++ /dev/null @@ -1,321 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { Arguments } from "yargs"; -import { ICommandDefinition } from "../doc/ICommandDefinition"; -import { IProfile, IProfileLoaded, IProfileManagerFactory, ProfileUtils } from "../../../profiles"; -import { ICommandProfileTypeConfiguration } from "../doc/profiles/definition/ICommandProfileTypeConfiguration"; -import { CommandProfiles } from "./CommandProfiles"; -import { inspect } from "util"; -import { ICommandLoadProfile } from "../doc/profiles/parms/ICommandLoadProfile"; -import { ICommandProfileLoaderParms } from "../doc/profiles/parms/ICommandProfileLoaderParms"; -import { Logger } from "../../../logger"; -import { ImperativeExpect } from "../../../expect"; -import { ImperativeError } from "../../../error"; -import { ImperativeConfig } from "../../../utilities"; - -/** - * The command processor profile loader loads all profiles that are required (or optional) given a command - * definitions requirements. It returns the CommandProfiles object (which contains the map and getters for the - * command handlers usage). - * @export - * @class CommandProfileLoader - */ -export class CommandProfileLoader { - /** - * Create a new instance of the profile loader - * @static - * @param {CommandResponse} response - The command response object, used to formulate messages, logs and errors - * @param {ICommandDefinition} commandDefinition - The command definition for the command being issued (used to determine - * what profiles to load for this command) - * @param {IProfileManagerFactory} factory - The profile manager factory (used to - * obtain instances of profile managers for profiles that are to be loaded) - * @returns - * @memberof CommandProfileLoader - */ - public static loader(parms: ICommandProfileLoaderParms) { - return new CommandProfileLoader(parms.commandDefinition, parms.profileManagerFactory, - parms.logger || Logger.getImperativeLogger()); - } - - /** - * The input command definition for the command being issued. - * @private - * @type {ICommandDefinition} - * @memberof CommandProfileLoader - */ - private mCommandDefinition: ICommandDefinition; - - /** - * The factory for getting profile manager instances. - * @private - * @type {IProfileManagerFactory} - * @memberof CommandProfileLoader - */ - private mFactory: IProfileManagerFactory; - - /** - * Logger - supplied on the constructor - but defaults to the Imperative logger. - * @private - * @type {Logger} - * @memberof CommandProfileLoader - */ - private mLog: Logger; - - /** - * Creates an instance of CommandProfileLoader. - * @param {ICommandDefinition} commandDefinition - The input command definition for the command being issued. - * @param {IProfileManagerFactory} factory - The profile manager factory - * @param {any} [logger=Logger.getImperativeLogger()] - A log4js instance - * @memberof CommandProfileLoader - */ - constructor(commandDefinition: ICommandDefinition, factory: IProfileManagerFactory, - logger = Logger.getImperativeLogger()) { - const err: string = "Could not construct the profile loader."; - ImperativeExpect.toNotBeNullOrUndefined(commandDefinition, `${err} No command definition supplied.`); - ImperativeExpect.toNotBeNullOrUndefined(factory, `${err} No profile factory supplied.`); - this.mCommandDefinition = commandDefinition; - this.mFactory = factory; - ImperativeExpect.toBeEqual((logger instanceof Logger), true, `${err} The "logger" supplied is not of type Logger.`); - this.mLog = logger; - this.log.trace(`Profile loader created for command: ${commandDefinition.name}`); - } - - /** - * Load the profiles for the command - the command arguments are supplied to grab the profile names from - * the arguments supplied by the user. - * @param {Arguments} commandArguments - The command arguments supplied on this command invocation (Yargs style) - * @returns {Promise} - The promise is fulfilled with the map object OR rejected with an - * Imperative error - * @memberof CommandProfileLoader - */ - public async loadProfiles(commandArguments: Arguments): Promise { - // Validate parms - ImperativeExpect.toNotBeNullOrUndefined(commandArguments, `Could not load profiles. No command arguments supplied.`); - - // Log the API call - this.log.info(`Request to load profiles for command: ${this.definition.name}...`); - this.log.trace(`Profile load arguments supplied:\n${inspect(commandArguments, {depth: null})}`); - - // Create the map that eventually will be returned - const profileMap: Map = new Map(); - const profileMetaMap: Map = new Map(); - - // do not load old school profiles if we are in team-config mode - if (ImperativeConfig.instance.config?.exists) { - return new CommandProfiles(profileMap, profileMetaMap); - } - - // If there are no profile specifications on this command definition document node, then - // we can immediately exit with an empty map - if (!(this.definition.profile == null)) { - this.log.trace(`Loading profiles for command: ${this.definition.name}...`); - const loadList: ICommandLoadProfile[] = this.constructLoadList(commandArguments); - const responses: IProfileLoaded[] = await this.loadAll(loadList); - this.log.debug(`"${responses.length}" profiles loaded.`); - this.buildCommandMap(responses, profileMap); - this.buildCommandMetaMap(responses, profileMetaMap); - this.log.trace(`All profiles loaded for command: ${this.definition.name}...`); - } - - // Return the command profiles object for the handler - return new CommandProfiles(profileMap, profileMetaMap); - - } - - /** - * Builds the command map for input the the command map object for the command handlers - * @private - * @param {IProfileLoaded[]} responses - The full list of profiles loaded for this command - * @param {Map} map - The map to populate - * @memberof CommandProfileLoader - */ - private buildCommandMap(responses: IProfileLoaded[], map: Map) { - for (const resp of responses) { - if (resp.profile) { - if (map.get(resp.type) == null) { - this.log.trace(`Adding first profile "${resp.name}" of type "${resp.type}" to the map.`); - map.set(resp.type, [resp.profile]); - } else { - this.log.trace(`Adding profile "${resp.name}" of type "${resp.type}" to the map.`); - const existing = map.get(resp.type); - existing.push(resp.profile); - } - } else { - this.log.debug(`Profile load response without a profile: ${resp.message}`); - } - } - } - - /** - * Builds the command meta map for input the the command map object for the command handlers - * @private - * @param {IProfileLoaded[]} responses - The full list of profiles loaded for this command - * @param {Map} map - The meta map to populate - * @memberof CommandProfileLoader - */ - private buildCommandMetaMap(responses: IProfileLoaded[], map: Map) { - for (const resp of responses) { - if (resp.profile) { - if (map.get(resp.type) == null) { - this.log.trace(`Adding first profile "${resp.name}" of type "${resp.type}" to the map.`); - map.set(resp.type, [resp]); - } else { - this.log.trace(`Adding profile "${resp.name}" of type "${resp.type}" to the map.`); - const existing = map.get(resp.type); - existing.push(resp); - } - } else { - this.log.debug(`Profile load response without a profile: ${resp.message}`); - } - } - } - - /** - * Builds the list of profiles to load for this command. - * @private - * @param {Arguments} commandArguments - The arguments supplied on the command (Yargs Style) - * @returns {ICommandLoadProfile[]} - The list of profiles to load (and other control information) - * @memberof CommandProfileLoader - */ - private constructLoadList(commandArguments: Arguments): ICommandLoadProfile[] { - let loadProfiles: ICommandLoadProfile[] = []; - this.log.trace(`Building required profiles for the load list...`); - loadProfiles = this.buildLoad(false, this.definition.profile.required, commandArguments); - this.log.trace(`Building optional profiles to the load list...`); - return loadProfiles.concat(this.buildLoad(true, this.definition.profile.optional, commandArguments)); - } - - /** - * Builds the control parameters for the loading of each profile name/type. - * @private - * @param {boolean} optional - If the profile is optional - * @param {string[]} types - The profile types to load - * @param {Arguments} commandArguments - The command arguments - * @returns {ICommandLoadProfile[]} - The list of profiles to load (and control parameters) - * @memberof CommandProfileLoader - */ - private buildLoad(optional: boolean, types: string[], commandArguments: Arguments): ICommandLoadProfile[] { - const loadProfiles: ICommandLoadProfile[] = []; - if (!(types == null)) { - // Construct the load control parameters for each required type - types.forEach((type) => { - - // Assume some defaults - const load: ICommandLoadProfile = { - name: undefined, - type, - userSpecified: false, - loadDefault: false, - optional - }; - - // If the argument is specified, indicate that this is a user specified load and if not - // assume that the default should be loaded (but still required on the command) - const profOpt = ProfileUtils.getProfileOptionAndAlias(type)[0]; - if (!(commandArguments[profOpt] == null)) { - load.userSpecified = true; - load.name = commandArguments[profOpt] as string; - } else { - load.loadDefault = true; - } - - // Add to the list - this.log.trace(`Adding load parameters to list: ${inspect(load, {depth: null})}`); - loadProfiles.push(load); - }); - } - - // Return the list - return loadProfiles; - } - - /** - * Invoke the profile managers to load the profiles requested for this command. - * @private - * @param {ICommandLoadProfile[]} list - The list of profiles to load and control parameters. - * @returns {Promise} - The promise to fulfill with the entire load response OR rejected with - * an Imperative Error. - * @memberof CommandProfileLoader - */ - private async loadAll(list: ICommandLoadProfile[]): Promise { - - // Attempt to load each profile indicated by the load control parameters - const loadResponses: IProfileLoaded[] = []; - for (const load of list) { - this.log.debug(`Loading profile "${load.name}" of type "${load.type}".`); - const response = await this.factory.getManager(load.type).load({ - loadDefault: load.loadDefault, - name: load.name, - failNotFound: !load.optional - }); - - // This is an exceptional case - the manager did not do it's job properly, but we will ensure - // that if a profile was required (not optional), that it was loaded. - if (!load.optional && (response == null || response.profile == null)) { - throw new ImperativeError({ - msg: `Unexpected internal load error: The profile ` + - `"${(load.loadDefault) ? "default requested" : load.name}" was not loaded by the profile manager.` - }); - } - - // Push the loaded resposne - this.log.debug(`Adding dependencies "${response.name}" of type "${response.type}"`); - loadResponses.push(response); - - // If dependencies have been loaded, we'll flatten the tree and push on the response list. - if (response.dependenciesLoaded) { - this.log.trace(`Dependencies have also been loaded, adding to list...`); - const flatten = ProfileUtils.flattenDependencies(response.dependencyLoadResponses); - for (const flat of flatten) { - this.log.debug(`Adding dependencies "${flat.name}" of type "${flat.type}"`); - loadResponses.push(flat); - } - } - } - - // Return the full list of load responses - return loadResponses; - } - - /** - * Accessor for the profile manager factory - * @readonly - * @private - * @type {IProfileManagerFactory} - * @memberof CommandProfileLoader - */ - private get factory(): IProfileManagerFactory { - return this.mFactory; - } - - /** - * Accessor for the command definition document - * @readonly - * @private - * @type {ICommandDefinition} - * @memberof CommandProfileLoader - */ - private get definition(): ICommandDefinition { - return this.mCommandDefinition; - } - - /** - * Accessor for the logging object - * @readonly - * @private - * @type {Logger} - * @memberof CommandProfileLoader - */ - private get log(): Logger { - return this.mLog; - } -} diff --git a/packages/imperative/src/cmd/src/profiles/CommandProfiles.ts b/packages/imperative/src/cmd/src/profiles/CommandProfiles.ts deleted file mode 100644 index 001dc1a14c..0000000000 --- a/packages/imperative/src/cmd/src/profiles/CommandProfiles.ts +++ /dev/null @@ -1,210 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ImperativeError } from "../../../error"; -import { IProfile, IProfileLoaded } from "../../../profiles"; -import { ImperativeExpect } from "../../../expect"; - -/** - * Profiles map created by the command profile loader and passed to the handler via parameters. Handlers can - * retreive loaded profiles from the map via the profile type. - * @export - * @class CommandProfiles - */ -export class CommandProfiles { - /** - * The loaded profiles map - profiles are retrieved via the type key. More than one profile of a particular type - * can be loaded by the command processor (depending on dependencies, etc.) - * @private - * @type {Map} - * @memberof CommandProfiles - */ - private mMap: Map; - - /** - * The loaded profiles map with meta info - profiles are retrieved via the type key. More than one profile of a particular type - * can be loaded by the command processor (depending on dependencies, etc.) - * @private - * @type {Map} - * @memberof CommandProfiles - */ - private mMetaMap: Map = new Map(); - - /** - * Creates an instance of CommandProfiles. - * @param {Map} map - The map of profiles - * @memberof CommandProfiles - */ - constructor(map: Map, metaMap?: Map) { - // Simple validation of input parameters - const err: string = "Command Profiles Internal Error:"; - ImperativeExpect.toNotBeNullOrUndefined(map, `${err} No map was supplied.`); - ImperativeExpect.toBeEqual(map instanceof Map, true, `${err} The "map" supplied is not an instance of a map.`); - - // Ensure the correctness of each map entry - map.forEach((value, key) => { - ImperativeExpect.toBeAnArray(value, `${err} The "profiles" supplied for type "${key}" is NOT an array.`); - ImperativeExpect.toBeEqual((value.length > 0), true, `${err} No profiles supplied for type "${key}".`); - }); - this.mMap = map; - - if (metaMap) { - this.addMeta(metaMap); - } - } - - /** - * Gets the first (or by name) meta profile in the map - automatically throws an exception (unless disabled) - * @deprecated - * @template T - The expected profile mapping to be returned - * @param {string} type - The profile type - * @param {string} [name=""] - The name of the profile to retrieve - * @param {boolean} [failNotFound=true] - Automatically throws an imperative exception if not profiles are not - * found - this is provided as convince for the handlers (will fail your command if not found) - This would - * normally be the result of a command configuration problem. - * @returns {T} - The first profile in the map (or the one located by name) - * @memberof CommandProfiles - */ - public getMeta(type: string, failNotFound = true, name = ""): T { - let profile: IProfileLoaded; - // If a profile is returned for the type, then we'll check if a profile of a specific name was requseted - // if not, just return the first profile found (first loaded) - if (this.metaMap.get(type) != null) { - if (name != null && name.trim().length > 0) { - for (const prof of this.metaMap.get(type)) { - - if (prof.name === name) { - profile = prof; - break; - } - } - } else { - profile = this.metaMap.get(type)[0]; - } - } else if (failNotFound) { - this.fail(type); - } - return profile as T; - } - - - /** - * Gets the first (or by name) profile in the map - automatically throws an exception (unless disabled) - * @deprecated Load profile properties from `IHandlerParameters.arguments` property instead. - * @template T - The expected profile mapping to be returned - * @param {string} type - The profile type - * @param {string} [name=""] - The name of the profile to retrieve - * @param {boolean} [failNotFound=true] - Automatically throws an imperative exception if not profiles are not - * found - this is provided as convince for the handlers (will fail your command if not found) - This would - * normally be the result of a command configuration problem. - * @returns {T} - The first profile in the map (or the one located by name) - * @memberof CommandProfiles - */ - public get(type: string, failNotFound = true, name = ""): T { - let profile: IProfile; - // If a profile is returned for the type, then we'll check if a profile of a specific name was requseted - // if not, just return the first profile found (first loaded) - if (this.map.get(type) != null) { - if (name != null && name.trim().length > 0) { - for (const prof of this.map.get(type)) { - - if (prof.name === name) { - profile = prof; - break; - } - } - } else { - profile = this.map.get(type)[0]; - } - } else if (failNotFound) { - this.fail(type); - } - return profile as T; - } - - /** - * Gets all profiles for the type specified, - * @deprecated - * @template T - extends IProfile - * @param {string} type - The profile type to retrieve loaded profiles - * @returns {T[]} - The list of profile types - * @param {boolean} [failNotFound=true] - Automatically throws an imperative exception if not profiles are not - * found - this is provided as convince for the handlers (will fail your command if not found) - This would - * normally be the result of a command configuration problem. - * @memberof CommandProfiles - */ - public getAll(type: string, failNotFound = true): T[] { - const profiles: IProfile[] = this.map.get(type); - if (profiles == null && failNotFound) { - this.fail(type); - } - return profiles as T[]; - } - - /** - * Add to an instance of CommandProfiles - * @private - * @param {Map} map - The map of profiles with meta information - * @memberof CommandProfiles - */ - private addMeta(map: Map) { - // Simple validation of input parameters - const err: string = "Command Profiles Internal Error:"; - ImperativeExpect.toNotBeNullOrUndefined(map, `${err} No map was supplied.`); - ImperativeExpect.toBeEqual(map instanceof Map, true, `${err} The "map" supplied is not an instance of a map.`); - - // Ensure the correctness of each map entry - map.forEach((value, key) => { - ImperativeExpect.toBeAnArray(value, `${err} The "profiles" supplied for type "${key}" is NOT an array.`); - ImperativeExpect.toBeEqual((value.length > 0), true, `${err} No profiles supplied for type "${key}".`); - }); - this.mMetaMap = map; - } - - /** - * Internal accessor for the map - * @readonly - * @private - * @type {Map} - The profile Map - * @memberof CommandProfiles - */ - private get map(): Map { - return this.mMap; - } - - /** - * Internal accessor for the meta map - * @readonly - * @private - * @type {Map} - The profile Map - * @memberof CommandProfiles - */ - private get metaMap(): Map { - return this.mMetaMap; - } - - /** - * Throw an error failing the get(requested by the caller if no profiles are available) - * @private - * @param {string} type - the profile type to get from the map - * @memberof CommandProfiles - */ - private fail(type: string) { - throw new ImperativeError({ - msg: `Internal Error: No profiles of type "${type}" were loaded for this command.`, - additionalDetails: `This error can occur for one of two reasons:\n` + - ` - The "profile" property on the command definition document ` + - `does NOT specify the requested profile type\n` + - ` - The profile type is marked "optional", no profiles of type "${type}" have been created, ` + - `and the command handler requested a profile of type "${type}" with "failNotFound=true"` - }); - } -} diff --git a/packages/imperative/src/cmd/src/response/CommandResponse.ts b/packages/imperative/src/cmd/src/response/CommandResponse.ts index 2c25263ec6..d35af49898 100644 --- a/packages/imperative/src/cmd/src/response/CommandResponse.ts +++ b/packages/imperative/src/cmd/src/response/CommandResponse.ts @@ -34,7 +34,8 @@ import * as tty from "tty"; import { IPromptOptions } from "../doc/response/api/handler/IPromptOptions"; import { DaemonRequest } from "../../../utilities/src/DaemonRequest"; import { IDaemonResponse } from "../../../utilities/src/doc/IDaemonResponse"; -import { Logger, LoggerUtils } from "../../../logger"; +import { Logger } from "../../../logger"; +import { LoggerUtils } from "../../../logger/src/LoggerUtils"; const DataObjectParser = require("dataobject-parser"); @@ -215,18 +216,18 @@ export class CommandResponse implements ICommandResponseApi { * @memberof CommandResponse */ constructor(params?: ICommandResponseParms) { - this.mControl = (params == null) ? {} : params; + this.mControl = params == null ? {} : params; this.mArguments = this.mControl.args; this.mDefinition = this.mControl.definition; this.mPrimaryTextColor = this.mControl.primaryTextColor == null ? this.mPrimaryTextColor : this.mControl.primaryTextColor; ImperativeExpect.toNotBeEqual(this.mPrimaryTextColor.trim(), "", `${CommandResponse.RESPONSE_ERR_TAG} The primary text color supplied is blank. Must provide a valid color.`); const formats: string[] = ["json", "default"]; - this.mResponseFormat = (this.mControl.responseFormat == null) ? "default" : this.mControl.responseFormat; + this.mResponseFormat = this.mControl.responseFormat == null ? "default" : this.mControl.responseFormat; ImperativeExpect.toBeOneOf(this.mResponseFormat, formats, `${CommandResponse.RESPONSE_ERR_TAG} Response format invalid. Valid formats: "${formats.join(",")}"`); - this.mSilent = (this.mControl.silent == null) ? false : this.mControl.silent; - this.mProgressBarSpinnerChars = (this.mControl.progressBarSpinner == null) ? this.mProgressBarSpinnerChars : this.mControl.progressBarSpinner; + this.mSilent = this.mControl.silent == null ? false : this.mControl.silent; + this.mProgressBarSpinnerChars = this.mControl.progressBarSpinner == null ? this.mProgressBarSpinnerChars : this.mControl.progressBarSpinner; this.mStream = params ? params.stream : undefined; } @@ -251,8 +252,8 @@ export class CommandResponse implements ICommandResponseApi { `Output format must be one of the following: ${OptionConstants.RESPONSE_FORMAT_TYPES.toString()}`); // If the output is an array and the length is 0 or - do nothing - if ((Array.isArray(format.output) && format.output.length === 0) || - (Object.keys(format.output).length === 0 && format.output.constructor === Object)) { + if (Array.isArray(format.output) && format.output.length === 0 || + Object.keys(format.output).length === 0 && format.output.constructor === Object) { return; } @@ -271,11 +272,11 @@ export class CommandResponse implements ICommandResponseApi { // Depending on the command definition and arguments, override the format options if (outer.mDefinition != null && outer.mDefinition.outputFormatOptions != null) { - formatCopy.format = (outer.mArguments != null && outer.mArguments.responseFormatType != null) ? + formatCopy.format = outer.mArguments != null && outer.mArguments.responseFormatType != null ? outer.mArguments.responseFormatType : formatCopy.format; - formatCopy.fields = (outer.mArguments != null && outer.mArguments.responseFormatFilter != null) ? + formatCopy.fields = outer.mArguments != null && outer.mArguments.responseFormatFilter != null ? outer.mArguments.responseFormatFilter : formatCopy.fields; - formatCopy.header = (outer.mArguments != null && outer.mArguments.responseFormatHeader != null) ? + formatCopy.header = outer.mArguments != null && outer.mArguments.responseFormatHeader != null ? outer.mArguments.responseFormatHeader : formatCopy.header; } @@ -303,7 +304,7 @@ export class CommandResponse implements ICommandResponseApi { private formatOutput(params: ICommandOutputFormat, response: CommandResponse) { // If a single filter is specified, save the field the data was extracted from - const extractedFrom = (params.fields != null && params.fields.length === 1 && typeof params.output !== "string") ? + const extractedFrom = params.fields != null && params.fields.length === 1 && typeof params.output !== "string" ? params.fields[0] : undefined; // If filter fields are present, filter the object @@ -386,7 +387,7 @@ export class CommandResponse implements ICommandResponseApi { // Build the table table = TextUtils.getTable(params.output, "yellow", CommandResponse.MAX_COLUMN_WIDTH, - (params.header != null) ? params.header : false); + params.header != null ? params.header : false); } catch (tableErr) { throw new ImperativeError({ msg: `Error formulating table for command response. ` + @@ -423,8 +424,8 @@ export class CommandResponse implements ICommandResponseApi { private errorDetails(params: ICommandOutputFormat, appliedTo: string, extractedFrom?: string): string { return `The format type of "${params.format}" can only be applied to ${appliedTo}.\n` + `The data being formatted is of type ` + - `"${(Array.isArray(params.output)) ? "array" : typeof params.output}".` + - `${(extractedFrom != null) ? `\nNote that the data being formatted was extracted from property "${extractedFrom}" ` + + `"${Array.isArray(params.output) ? "array" : typeof params.output}".` + + `${extractedFrom != null ? `\nNote that the data being formatted was extracted from property "${extractedFrom}" ` + `because that field was specified as the single filter.` : ""}`; } @@ -647,7 +648,7 @@ export class CommandResponse implements ICommandResponseApi { * completely overwritten. */ public setObj(data: any, merge = false) { - outer.mData = (merge) ? DeepMerge(outer.mData, data) : data; + outer.mData = merge ? DeepMerge(outer.mData, data) : data; } /** @@ -725,13 +726,13 @@ export class CommandResponse implements ICommandResponseApi { }); } if (!outer.silent && outer.mResponseFormat !== "json" && - !(TextUtils.chalk.level === 0 || !TextUtils.chalk.enabled || process.env.CI != null)) { + !(TextUtils.chalk.level === 0 || process.env.CI != null)) { // Persist the task specifications and determine the stream to use for the progress bar this.mProgressBarStdoutStartIndex = outer.mStdout.length; this.mProgressBarStderrStartIndex = outer.mStderr.length; this.mProgressTask = params.task; - let stream: any = (params.stream == null) ? process.stderr : params.stream; + let stream: any = params.stream == null ? process.stderr : params.stream; const arbitraryColumnSize = 80; // if we have an outer stream (e.g. socket connection for daemon mode) use it @@ -766,7 +767,7 @@ export class CommandResponse implements ICommandResponseApi { // Set the interval based on the params of the default this.mProgressBarInterval = setInterval(this.updateProgressBar.bind(this), - (params.updateInterval == null) ? this.mProgressBarPollFrequency : params.updateInterval); + params.updateInterval == null ? this.mProgressBarPollFrequency : params.updateInterval); } } @@ -870,7 +871,7 @@ export class CommandResponse implements ICommandResponseApi { * @memberof CommandResponse */ public bufferStdout(data: Buffer | string) { - this.mStdout = Buffer.concat([this.mStdout, ((data instanceof Buffer) ? data : Buffer.from(data))]); + this.mStdout = Buffer.concat([this.mStdout, data instanceof Buffer ? data : Buffer.from(data)]); } /** @@ -880,7 +881,7 @@ export class CommandResponse implements ICommandResponseApi { * @memberof CommandResponse */ public bufferStderr(data: Buffer | string) { - this.mStderr = Buffer.concat([this.mStderr, ((data instanceof Buffer) ? data : Buffer.from(data))]); + this.mStderr = Buffer.concat([this.mStderr, data instanceof Buffer ? data : Buffer.from(data)]); } /** diff --git a/packages/imperative/src/cmd/src/syntax/SyntaxValidator.ts b/packages/imperative/src/cmd/src/syntax/SyntaxValidator.ts index 5da6f410a0..ea0b0be56b 100644 --- a/packages/imperative/src/cmd/src/syntax/SyntaxValidator.ts +++ b/packages/imperative/src/cmd/src/syntax/SyntaxValidator.ts @@ -122,13 +122,13 @@ export class SyntaxValidator { /** * Prevent empty string options, regardless of if they are - * required or not e.g. --bright-zosmf-profile (without a value) + * required or not e.g. --zosmf-profile (without a value) */ if (!(this.mCommandDefinition.options == null)) { for (const option of this.mCommandDefinition.options) { if (!(commandArguments[option.name] == null) && (option.type !== "stringOrEmpty" && commandArguments[option.name] === "") || - (option.type !== "boolean" && commandArguments[option.name] === true)) { + option.type !== "boolean" && commandArguments[option.name] === true) { valid = false; this.emptyValueError(responseObject, option.name); } @@ -209,7 +209,7 @@ export class SyntaxValidator { // Use replace to trim possible ... which is used for arrays const positionalName = positional.name.replace("...", ""); if (commandArguments[positionalName] == null || - (positional.type !== "stringOrEmpty" && commandArguments[positionalName] === "")) { + positional.type !== "stringOrEmpty" && commandArguments[positionalName] === "") { missingPositionals.push(positional); } } @@ -226,7 +226,7 @@ export class SyntaxValidator { if (!(commandArguments[positional.name] == null)) { if (positional.regex) { if (commandArguments[positional.name] - .toString().match(new RegExp(positional.regex)) == null) { + .toString().match(new RegExp(positional.regex) == null)) { valid = false; this.positionalParameterInvalid(positional, commandArguments[positional.name], responseObject); @@ -234,6 +234,14 @@ export class SyntaxValidator { } if (positional.type === "number") { valid = this.validateNumeric(commandArguments[positional.name], positional, responseObject, true) && valid; + // Convert to number for backwards compatability + if (valid) { + const changedOptions: ICommandArguments = CliUtils.setOptionValue(positional.name, + [], parseFloat(commandArguments[positional.name])); + for (const [k, v] of Object.entries(changedOptions)) { + commandArguments[k] = v; + } + } } if (!(positional.stringLengthRange == null) && @@ -373,11 +381,17 @@ export class SyntaxValidator { commandArguments[optionDef.name]); } } else if (optionDef.type === "boolean") { - valid = this.validateBoolean(commandArguments[optionDef.name], optionDef, - responseObject) && valid; + valid = this.validateBoolean(commandArguments[optionDef.name], optionDef, responseObject) && valid; } else if (optionDef.type === "number") { - valid = this.validateNumeric(commandArguments[optionDef.name], optionDef, - responseObject) && valid; + valid = this.validateNumeric(commandArguments[optionDef.name], optionDef, responseObject) && valid; + // Convert to numbers for backwards compatibility - sets all possible values + if (valid) { + const changedOptions: ICommandArguments = CliUtils.setOptionValue(optionDef.name, + optionDef.aliases ?? [], parseFloat(commandArguments[optionDef.name])); + for (const [k, v] of Object.entries(changedOptions)) { + commandArguments[k] = v; + } + } } /** * Validate that the option's value is valid json. @@ -426,10 +440,10 @@ export class SyntaxValidator { for (const value of Object.keys(optionDef.valueImplications)) { const implicationObject: ICommandOptionValueImplications = optionDef.valueImplications[value]; - if ((implicationObject.isCaseSensitive && - commandArguments[optionName] === value) || - (!implicationObject.isCaseSensitive && - commandArguments[optionName].toUpperCase() === value.toUpperCase())) { + if (implicationObject.isCaseSensitive && + commandArguments[optionName] === value || + !implicationObject.isCaseSensitive && + commandArguments[optionName].toUpperCase() === value.toUpperCase()) { for (const impliedOption of implicationObject.impliedOptionNames) { if (!util.optionWasSpecified(impliedOption, this.mCommandDefinition, commandArguments)) { @@ -504,7 +518,7 @@ export class SyntaxValidator { if (!isPositional) { const def = optionDefinition as ICommandOptionDefinition; - aliasString = (!(def.aliases == null) && def.aliases.length > 0) ? + aliasString = def.aliases != null && def.aliases.length > 0 ? "(" + def.aliases.map((alias: string) => { return this.getDashFormOfOption(alias); }).join(",") + ")" : ""; @@ -615,8 +629,8 @@ export class SyntaxValidator { let valid: boolean = true; const min = optionDefinition.numericValueRange[0]; const max = optionDefinition.numericValueRange[1]; - if ((optionValue < min) || - (optionValue > max)) { + if (optionValue < min || + optionValue > max) { responseObject.console.errorHeader(syntaxErrorHeader.message); const msg: string = responseObject.console.error("Invalid numeric value specified for option:\n{{option}}\n\n" + "You specified:\n{{value}}\n\n" + @@ -705,7 +719,7 @@ export class SyntaxValidator { {message: msg, optionInError: optionDefinition.name, definition: optionDefinition}); } - const valid = (duplicateValuesSet.size === 0); + const valid = duplicateValuesSet.size === 0; return valid; } @@ -1033,8 +1047,8 @@ export class SyntaxValidator { } /** - * Append the validator error to the resposne object. - * @param {CommandResponse} responseObject: The Brightside response object + * Append the validator error to the response object. + * @param {CommandResponse} responseObject: The Zowe response object * @param {ICommandValidatorError} error: The error to append. */ private appendValidatorError(responseObject: CommandResponse, error: ICommandValidatorError) { diff --git a/packages/imperative/src/cmd/src/syntax/__mocks__/SyntaxValidator.ts b/packages/imperative/src/cmd/src/syntax/__mocks__/SyntaxValidator.ts index 4c99f87760..f30aa4d2a9 100644 --- a/packages/imperative/src/cmd/src/syntax/__mocks__/SyntaxValidator.ts +++ b/packages/imperative/src/cmd/src/syntax/__mocks__/SyntaxValidator.ts @@ -19,7 +19,7 @@ export class SyntaxValidator { if (commandArguments.syntaxThrow === true) { throw new Error("Syntax validation error!"); } else { - validationComplete({ valid: (commandArguments.valid == null) ? false : commandArguments.valid as boolean }); + validationComplete({ valid: commandArguments.valid == null ? false : commandArguments.valid as boolean }); } }); } diff --git a/packages/imperative/src/cmd/src/syntax/__tests__/SyntaxValidator.unit.test.ts b/packages/imperative/src/cmd/src/syntax/__tests__/SyntaxValidator.unit.test.ts index 2d8c31330c..58bf12a29c 100644 --- a/packages/imperative/src/cmd/src/syntax/__tests__/SyntaxValidator.unit.test.ts +++ b/packages/imperative/src/cmd/src/syntax/__tests__/SyntaxValidator.unit.test.ts @@ -15,14 +15,27 @@ import { TextUtils } from "../../../../utilities"; jest.mock("../../../../imperative/src/Imperative"); import { inspect } from "util"; import { TestLogger } from "../../../../../__tests__/src/TestLogger"; -import { CommandResponse, ICommandDefinition, ICommandValidatorResponse } from "../../../"; +import { ICommandValidatorResponse } from "../../doc/response/response/ICommandValidatorResponse"; +import { CommandResponse, ICommandDefinition } from "../../../"; import { ValidationTestCommand } from "../../../../../__tests__/src/packages/cmd/ValidationTestCommand"; import { SyntaxValidator } from "../SyntaxValidator"; import { Constants } from "../../../../constants"; +import { YargsConfigurer } from "../../yargs/YargsConfigurer"; describe("Imperative should provide advanced syntax validation rules", () => { const logger = TestLogger.getTestLogger(); + const aliases: Record = {}; + // We define ValidationTestCommand. Options is always defined. + for (const option of ValidationTestCommand.options!) { + if (option.aliases) { + aliases[option.name] = option.aliases; + } + } + const configuration = { + configuration: YargsConfigurer.yargsConfiguration, + alias: aliases + }; describe("Advanced syntax validation for commands using a test command", () => { const yargsParser = require("yargs-parser"); @@ -32,7 +45,7 @@ describe("Imperative should provide advanced syntax validation rules", () => { function tryOptions(optionString: string, shouldSucceed: boolean, expectedText?: string[]) { - const options = yargsParser(optionString); + const options = yargsParser.detailed(optionString, configuration).argv; options._ = ["test", "validation-test"].concat(options._ || []); // fake out command structure options[Constants.JSON_OPTION] = true; delete options["--"]; // delete extra yargs parse field @@ -361,6 +374,157 @@ describe("Imperative should provide advanced syntax validation rules", () => { minValidOptions + "--always-required-string hello", false, ["multiple", "--always-required-string"])(); }); + + it("should validate that typed numbers are numbers, and convert strings that are numbers 1", async () => { + const options = yargsParser.detailed(minValidOptions + " --should-be-number 4", configuration).argv; + options._ = ["test", "validation-test"].concat(options._ || []); // fake out command structure + options[Constants.JSON_OPTION] = true; + delete options["--"]; // delete extra yargs parse field + logger.debug("Executing test syntax command with arguments: " + inspect(options)); + const response = new CommandResponse({responseFormat: "json"}); + const fakeParent: ICommandDefinition = { + name: undefined, + description: "", type: "group", + children: [ValidationTestCommand] + }; + const svResponse = await new SyntaxValidator(ValidationTestCommand, fakeParent).validate(response, options); + expect(options["should-be-number"]).toBe(4); + expect(options["shouldBeNumber"]).toBe(4); + expect(options["sbn"]).toBe(4); + expect(options["should-be-number"]).not.toBe("4"); + expect(options["shouldBeNumber"]).not.toBe("4"); + expect(options["sbn"]).not.toBe("4"); + expect(svResponse.valid).toEqual(true); + }); + + it("should validate that typed numbers are numbers, and convert strings that are numbers 2", async () => { + const options = yargsParser.detailed(minValidOptions + " --shouldBeNumber 4", configuration).argv; + options._ = ["test", "validation-test"].concat(options._ || []); // fake out command structure + options[Constants.JSON_OPTION] = true; + delete options["--"]; // delete extra yargs parse field + logger.debug("Executing test syntax command with arguments: " + inspect(options)); + const response = new CommandResponse({responseFormat: "json"}); + const fakeParent: ICommandDefinition = { + name: undefined, + description: "", type: "group", + children: [ValidationTestCommand] + }; + const svResponse = await new SyntaxValidator(ValidationTestCommand, fakeParent).validate(response, options); + expect(options["should-be-number"]).toBe(4); + expect(options["shouldBeNumber"]).toBe(4); + expect(options["sbn"]).toBe(4); + expect(options["should-be-number"]).not.toBe("4"); + expect(options["shouldBeNumber"]).not.toBe("4"); + expect(options["sbn"]).not.toBe("4"); + expect(svResponse.valid).toEqual(true); + }); + + it("should validate that typed numbers are numbers, and convert strings that are numbers 3", async () => { + const options = yargsParser.detailed(minValidOptions + " --sbn 4", configuration).argv; + options._ = ["test", "validation-test"].concat(options._ || []); // fake out command structure + options[Constants.JSON_OPTION] = true; + delete options["--"]; // delete extra yargs parse field + logger.debug("Executing test syntax command with arguments: " + inspect(options)); + const response = new CommandResponse({responseFormat: "json"}); + const fakeParent: ICommandDefinition = { + name: undefined, + description: "", type: "group", + children: [ValidationTestCommand] + }; + const svResponse = await new SyntaxValidator(ValidationTestCommand, fakeParent).validate(response, options); + expect(options["should-be-number"]).toBe(4); + expect(options["shouldBeNumber"]).toBe(4); + expect(options["sbn"]).toBe(4); + expect(options["should-be-number"]).not.toBe("4"); + expect(options["shouldBeNumber"]).not.toBe("4"); + expect(options["sbn"]).not.toBe("4"); + expect(svResponse.valid).toEqual(true); + }); + + it("should validate that typed numbers are numbers, and convert strings that are numbers that are floats 1", async () => { + const options = yargsParser.detailed(minValidOptions + " --should-be-number 3.1415926", configuration).argv; + options._ = ["test", "validation-test"].concat(options._ || []); // fake out command structure + options[Constants.JSON_OPTION] = true; + delete options["--"]; // delete extra yargs parse field + logger.debug("Executing test syntax command with arguments: " + inspect(options)); + const response = new CommandResponse({responseFormat: "json"}); + const fakeParent: ICommandDefinition = { + name: undefined, + description: "", type: "group", + children: [ValidationTestCommand] + }; + const svResponse = await new SyntaxValidator(ValidationTestCommand, fakeParent).validate(response, options); + expect(options["should-be-number"]).toBe(3.1415926); + expect(options["shouldBeNumber"]).toBe(3.1415926); + expect(options["sbn"]).toBe(3.1415926); + expect(options["should-be-number"]).not.toBe("3.1415926"); + expect(options["shouldBeNumber"]).not.toBe("3.1415926"); + expect(options["sbn"]).not.toBe("3.1415926"); + expect(svResponse.valid).toEqual(true); + }); + + it("should validate that typed numbers are numbers, and convert strings that are numbers that are floats 2", async () => { + const options = yargsParser.detailed(minValidOptions + " --shouldBeNumber 3.1415926", configuration).argv; + options._ = ["test", "validation-test"].concat(options._ || []); // fake out command structure + options[Constants.JSON_OPTION] = true; + delete options["--"]; // delete extra yargs parse field + logger.debug("Executing test syntax command with arguments: " + inspect(options)); + const response = new CommandResponse({responseFormat: "json"}); + const fakeParent: ICommandDefinition = { + name: undefined, + description: "", type: "group", + children: [ValidationTestCommand] + }; + const svResponse = await new SyntaxValidator(ValidationTestCommand, fakeParent).validate(response, options); + expect(options["should-be-number"]).toBe(3.1415926); + expect(options["shouldBeNumber"]).toBe(3.1415926); + expect(options["sbn"]).toBe(3.1415926); + expect(options["should-be-number"]).not.toBe("3.1415926"); + expect(options["shouldBeNumber"]).not.toBe("3.1415926"); + expect(options["sbn"]).not.toBe("3.1415926"); + expect(svResponse.valid).toEqual(true); + }); + + it("should validate that typed numbers are numbers, and convert strings that are numbers that are floats 3", async () => { + const options = yargsParser.detailed(minValidOptions + " --sbn 3.1415926", configuration).argv; + options._ = ["test", "validation-test"].concat(options._ || []); // fake out command structure + options[Constants.JSON_OPTION] = true; + delete options["--"]; // delete extra yargs parse field + logger.debug("Executing test syntax command with arguments: " + inspect(options)); + const response = new CommandResponse({responseFormat: "json"}); + const fakeParent: ICommandDefinition = { + name: undefined, + description: "", type: "group", + children: [ValidationTestCommand] + }; + const svResponse = await new SyntaxValidator(ValidationTestCommand, fakeParent).validate(response, options); + expect(options["should-be-number"]).toBe(3.1415926); + expect(options["shouldBeNumber"]).toBe(3.1415926); + expect(options["sbn"]).toBe(3.1415926); + expect(options["should-be-number"]).not.toBe("3.1415926"); + expect(options["shouldBeNumber"]).not.toBe("3.1415926"); + expect(options["sbn"]).not.toBe("3.1415926"); + expect(svResponse.valid).toEqual(true); + }); + + it("should validate that typed strings are strings and not numbers", async () => { + const options = yargsParser.detailed(minValidOptions + " --fluffy 9001", configuration).argv; + options._ = ["test", "validation-test"].concat(options._ || []); // fake out command structure + options[Constants.JSON_OPTION] = true; + delete options["--"]; // delete extra yargs parse field + logger.debug("Executing test syntax command with arguments: " + inspect(options)); + const response = new CommandResponse({responseFormat: "json"}); + const fakeParent: ICommandDefinition = { + name: undefined, + description: "", type: "group", + children: [ValidationTestCommand] + }; + const svResponse = await new SyntaxValidator(ValidationTestCommand, fakeParent).validate(response, options); + expect(options["fluffy"]).toBe("9001"); + expect(options["fluffy"]).not.toBe(9001); + expect(svResponse.valid).toEqual(true); + }); + describe("We should be able to validate positional arguments of type 'number'", () => { const numberCommand: ICommandDefinition = { name: "gimme-number", aliases: [], diff --git a/packages/imperative/src/cmd/src/utils/CommandUtils.ts b/packages/imperative/src/cmd/src/utils/CommandUtils.ts index 36a06442ac..b1328a6c83 100644 --- a/packages/imperative/src/cmd/src/utils/CommandUtils.ts +++ b/packages/imperative/src/cmd/src/utils/CommandUtils.ts @@ -164,17 +164,6 @@ export class CommandUtils { }); } - /** - * Accepts the command definition document tree and flattens to a single level, including aliases. This is used to make searching - * commands and others easily. - * @param {ICommandDefinition} tree - The command document tree - * @deprecated Use CommandUtils.flattenCommandTree instead - * @return {ICommandTreeEntry[]} - The flattened document tree - */ - public static flattenCommandTreeWithAliases(tree: ICommandDefinition): ICommandTreeEntry[] { - return CommandUtils.flattenCommandTree(tree, true); - } - /** * TODO - This needs to be well tested * TODO - There is a situation where two groups could have the same child command @@ -191,7 +180,12 @@ export class CommandUtils { const def = omit(treeEntry.command, "children"); if (isEqual(def, command)) { return treeEntry.fullName; } } + // otherwise, couldn't find it, just return the current name - return commandDef.name; + if(commandTree.name === undefined){ + return commandDef.name; + } else { + return commandTree.name + " " + commandDef.name; + } } } diff --git a/packages/imperative/src/cmd/src/utils/SharedOptions.ts b/packages/imperative/src/cmd/src/utils/SharedOptions.ts index f23e96696d..4fc7f07171 100644 --- a/packages/imperative/src/cmd/src/utils/SharedOptions.ts +++ b/packages/imperative/src/cmd/src/utils/SharedOptions.ts @@ -17,7 +17,7 @@ import { CommandResponse } from "../response/CommandResponse"; import { Logger } from "../../../logger"; /** - * Options which can be reused between different Brightside commands + * Options which can be reused between different Zowe commands */ export class SharedOptions { /** @@ -96,7 +96,7 @@ export class SharedOptions { const stdinReadError: IImperativeError = { msg: "Error encountered while reading from stdin", causeErrors: error, - additionalDetails: (error == null) ? undefined : error.message + additionalDetails: error == null ? undefined : error.message }; done(stdinReadError, true); // don't call done, we don't want to continue on an error diff --git a/packages/imperative/src/cmd/src/yargs/AbstractCommandYargs.ts b/packages/imperative/src/cmd/src/yargs/AbstractCommandYargs.ts index 9edb11cd0b..a179f2786b 100644 --- a/packages/imperative/src/cmd/src/yargs/AbstractCommandYargs.ts +++ b/packages/imperative/src/cmd/src/yargs/AbstractCommandYargs.ts @@ -19,8 +19,6 @@ import { IYargsParms } from "./doc/IYargsParms"; import { ICommandResponseParms } from "../../../cmd/src/doc/response/parms/ICommandResponseParms"; import { ImperativeYargsCommandAction, IYargsResponse } from "./doc/IYargsResponse"; import { GroupCommandYargs } from "./GroupCommandYargs"; -import { IProfileManagerFactory } from "../../../profiles"; -import { ICommandProfileTypeConfiguration } from "../doc/profiles/definition/ICommandProfileTypeConfiguration"; import { IHelpGeneratorFactory } from "../help/doc/IHelpGeneratorFactory"; import { CommandResponse } from "../response/CommandResponse"; import { ICommandResponse } from "../../src/doc/response/response/ICommandResponse"; @@ -33,7 +31,7 @@ import { ImperativeConfig } from "../../../utilities/src/ImperativeConfig"; export type YargsCommandCompleted = (args: Arguments, response: IYargsResponse) => void; /** - * Abstract Yargs Bright Command - Contains base methods for defining commands and groups + * Abstract Yargs Zowe Command - Contains base methods for defining commands and groups */ export abstract class AbstractCommandYargs { /** @@ -68,14 +66,6 @@ export abstract class AbstractCommandYargs { */ private mHelpGeneratorFactory: IHelpGeneratorFactory; - /** - * Profile manager factory (for creating managers of certain types) - * @private - * @type {IProfileManagerFactory} - * @memberof AbstractCommandYargs - */ - private mProfileManagerFactory: IProfileManagerFactory; - /** * The root command name for the CLI. * @private @@ -117,7 +107,6 @@ export abstract class AbstractCommandYargs { this.mDefinition = yargsParms.commandDefinition; this.mParent = yargsParms.yargsParent; this.mCommandResponseParms = yargsParms.commandResponseParms; - this.mProfileManagerFactory = yargsParms.profileManagerFactory; this.mHelpGeneratorFactory = yargsParms.helpGeneratorFactory; this.mRootCommandName = yargsParms.rootCommandName; this.mCommandLine = yargsParms.commandLine; @@ -186,16 +175,6 @@ export abstract class AbstractCommandYargs { return this.mHelpGeneratorFactory; } - /** - * Accessor for the profile manager factory - * @readonly - * @type {IProfileManagerFactory} - * @memberof AbstractCommandYargs - */ - protected get profileManagerFactory(): IProfileManagerFactory { - return this.mProfileManagerFactory; - } - /** * Returns a copy of the definition. * @return {ICommandDefinition}: A copy of the definition. @@ -226,12 +205,12 @@ export abstract class AbstractCommandYargs { } /** - * Construct the Bright command definition "tree" - the full definition document including all parents. + * Construct the Zowe command definition "tree" - the full definition document including all parents. * @return {ICommandDefinition}: The command definition "tree". */ public constructDefinitionTree(): ICommandDefinition { const parents: GroupCommandYargs[] = this.parents; - return (parents[0]) ? JSON.parse(JSON.stringify(parents[0].definition)) : {}; + return parents[0] ? JSON.parse(JSON.stringify(parents[0].definition)) : {}; } /** @@ -241,17 +220,7 @@ export abstract class AbstractCommandYargs { public abstract defineCommandToYargs(commandExecuted: YargsCommandCompleted): void; /** - * @deprecated Use `getZoweYargsResponse` instead - */ - protected getBrightYargsResponse(successful: boolean, responseMessage: string, - action: ImperativeYargsCommandAction, - responses?: ICommandResponse[]): IYargsResponse - { - return this.getZoweYargsResponse(successful, responseMessage, action, responses); - } - - /** - * Build The Bright Yargs response for the callback. Includes the Bright command response and status info. + * Build The Zowe Yargs response for the callback. Includes the Zowe command response and status info. * @param {boolean} successful: True if the command succeeded * @param {string} responseMessage: Response message for display purposes. * @param {ImperativeYargsCommandAction} action @@ -265,7 +234,7 @@ export abstract class AbstractCommandYargs { if (responses != null && responses.length > 0) { for (const response of responses) { // use the maximum exit code from all command responses - if (exitCode == null || (response.exitCode != null && response.exitCode > exitCode)) { + if (exitCode == null || response.exitCode != null && response.exitCode > exitCode) { exitCode = response.exitCode; } } @@ -290,7 +259,7 @@ export abstract class AbstractCommandYargs { * object is recreated/changed based on the currently specified CLI options */ let tempDefinition: ICommandDefinition; - if (args[Constants.HELP_EXAMPLES] && (this.definition.children.length > 0)) { + if (args[Constants.HELP_EXAMPLES] && this.definition.children.length > 0) { tempDefinition = this.getDepthExamples(); } @@ -307,7 +276,6 @@ export abstract class AbstractCommandYargs { definition: tempDefinition ? tempDefinition : this.definition, fullDefinition: tempDefinition ? tempDefinition : this.constructDefinitionTree(), helpGenerator: newHelpGenerator, - profileManagerFactory: this.profileManagerFactory, rootCommandName: this.rootCommandName, commandLine: this.commandLine, envVariablePrefix: this.envVariablePrefix, @@ -315,7 +283,7 @@ export abstract class AbstractCommandYargs { daemonContext: ImperativeConfig.instance.daemonContext }).help(new CommandResponse({ silent: false, - responseFormat: (args[Constants.JSON_OPTION] || false) ? "json" : "default", + responseFormat: args[Constants.JSON_OPTION] || false ? "json" : "default", stream: ImperativeConfig.instance.daemonContext?.stream })); } catch (helpErr) { @@ -355,7 +323,7 @@ export abstract class AbstractCommandYargs { commandDefinition.examples = []; } - lodashDeep.deepMapValues(this.definition.children, ((value: any, path: any) => { + lodashDeep.deepMapValues(this.definition.children, (value: any, path: any) => { if(path.endsWith("name") && (path.includes("options") || path.includes("positionals"))) { /* Do nothing */ } else if(path.endsWith("name") && path.includes("children")) { @@ -391,13 +359,13 @@ export abstract class AbstractCommandYargs { if(tempDescPath === tempOpPath ) { let commandExamples: ICommandExampleDefinition; - (tempPre && (tempDescPath === tempPrePath)) ? + tempPre && tempDescPath === tempPrePath ? commandDefinition.examples[commandDefinition.examples.length - 1].prefix = tempPre :commandExamples = {description: tempDesc, options: tempOp}; if(commandExamples) {commandDefinition.examples.push(commandExamples);} } } - })); + }); return commandDefinition; } @@ -419,7 +387,6 @@ export abstract class AbstractCommandYargs { definition: this.definition, fullDefinition: this.constructDefinitionTree(), helpGenerator: "fake" as any, - profileManagerFactory: this.profileManagerFactory, rootCommandName: this.rootCommandName, commandLine: this.commandLine, envVariablePrefix: this.envVariablePrefix, @@ -428,7 +395,7 @@ export abstract class AbstractCommandYargs { }).webHelp(fullCommandName + "_" + this.definition.name, new CommandResponse({ silent: false, - responseFormat: (args[Constants.JSON_OPTION] || false) ? "json" : "default", + responseFormat: args[Constants.JSON_OPTION] || false ? "json" : "default", stream: ImperativeConfig.instance.daemonContext?.stream }) ); diff --git a/packages/imperative/src/cmd/src/yargs/CommandYargs.ts b/packages/imperative/src/cmd/src/yargs/CommandYargs.ts index 5483a36956..637e8389d3 100644 --- a/packages/imperative/src/cmd/src/yargs/CommandYargs.ts +++ b/packages/imperative/src/cmd/src/yargs/CommandYargs.ts @@ -29,11 +29,11 @@ export class CommandYargs extends AbstractCommandYargs { /** * Define the options to Yargs. * @param {yargs.Argv} yargsInstance: The instance of yargs to define the options. - * @param {ICommandOptionDefinition[]} brightOptions: The option definition document array. + * @param {ICommandOptionDefinition[]} zoweOptions: The option definition document array. */ - public static defineOptionsToYargs(yargsInstance: Argv, brightOptions: ICommandOptionDefinition[]): void { - if (!(brightOptions == null)) { - for (const option of brightOptions) { + public static defineOptionsToYargs(yargsInstance: Argv, zoweOptions: ICommandOptionDefinition[]): void { + if (zoweOptions != null) { + for (const option of zoweOptions) { const definition: Options = { alias: option.aliases, description: option.description @@ -41,11 +41,10 @@ export class CommandYargs extends AbstractCommandYargs { if (!(option.type == null)) { // don't let yargs handle any types that we are validating ourselves // and don't use custom types as the yargs type since yargs won't understand - if (option.type !== "number" && - option.type !== "json") { - definition.type = option.type as any; - } else if (option.type === "json") { + if (option.type === "json" || option.type === "number") { definition.type = "string"; + } else { + definition.type = option.type as any; } } // If this is a boolean type option, default it to undefined so that we can distinguish @@ -176,9 +175,9 @@ export class CommandYargs extends AbstractCommandYargs { private buildPositionalString(): string { if (this.definition.positionals) { this.log.debug("Building positional string from: " + this.definition.name); - let yargPositionalSyntax: string = (this.definition.positionals.length > 0) ? " " : ""; + let yargPositionalSyntax: string = this.definition.positionals.length > 0 ? " " : ""; this.definition.positionals.forEach((positional) => { - yargPositionalSyntax += ("[" + positional.name + "] "); + yargPositionalSyntax += "[" + positional.name + "] "; }); const posString: string = yargPositionalSyntax.substring(0, yargPositionalSyntax.lastIndexOf(" ")); this.log.debug("Positional String: " + posString); @@ -210,7 +209,7 @@ export class CommandYargs extends AbstractCommandYargs { if (!AbstractCommandYargs.STOP_YARGS) { // Determine if we should print JSON - const printJson: boolean = (index === handlers.length - 1) && + const printJson: boolean = index === handlers.length - 1 && (argsForHandler[Constants.JSON_OPTION] as boolean); // Protect against issues allocating the command processor @@ -223,7 +222,6 @@ export class CommandYargs extends AbstractCommandYargs { fullCommandTree: this.constructDefinitionTree(), experimentalCommandsDescription: this.yargsParms.experimentalCommandDescription }), - profileManagerFactory: this.profileManagerFactory, rootCommandName: this.rootCommandName, commandLine: ImperativeConfig.instance.commandLine, envVariablePrefix: this.envVariablePrefix, @@ -233,7 +231,7 @@ export class CommandYargs extends AbstractCommandYargs { }).invoke({ arguments: argsForHandler, silent: false, - responseFormat: (printJson) ? "json" : "default" + responseFormat: printJson ? "json" : "default" }).then((commandHandlerResponse) => { /** * Push the responses - If an error occurs, reject the promise with the error response. @@ -259,7 +257,7 @@ export class CommandYargs extends AbstractCommandYargs { } catch (processorError) { const response = new CommandResponse({ silent: false, - responseFormat: (printJson) ? "json" : "default", + responseFormat: printJson ? "json" : "default", stream: ImperativeConfig.instance.daemonContext?.stream }); response.failed(); diff --git a/packages/imperative/src/cmd/src/yargs/GroupCommandYargs.ts b/packages/imperative/src/cmd/src/yargs/GroupCommandYargs.ts index e997dac74d..c7971d86bd 100644 --- a/packages/imperative/src/cmd/src/yargs/GroupCommandYargs.ts +++ b/packages/imperative/src/cmd/src/yargs/GroupCommandYargs.ts @@ -61,7 +61,6 @@ export class GroupCommandYargs extends AbstractCommandYargs { yargsParent: this, commandResponseParms: this.responseParms, helpGeneratorFactory: this.helpGeneratorFactory, - profileManagerFactory: this.profileManagerFactory, experimentalCommandDescription: this.yargsParms.experimentalCommandDescription, rootCommandName: this.rootCommandName, commandLine: this.commandLine, @@ -76,7 +75,6 @@ export class GroupCommandYargs extends AbstractCommandYargs { yargsParent: this, commandResponseParms: this.responseParms, helpGeneratorFactory: this.helpGeneratorFactory, - profileManagerFactory: this.profileManagerFactory, experimentalCommandDescription: this.yargsParms.experimentalCommandDescription, rootCommandName: this.rootCommandName, commandLine: this.commandLine, diff --git a/packages/imperative/src/cmd/src/yargs/YargsConfigurer.ts b/packages/imperative/src/cmd/src/yargs/YargsConfigurer.ts index 51c1f0c10d..2e6b1cfee7 100644 --- a/packages/imperative/src/cmd/src/yargs/YargsConfigurer.ts +++ b/packages/imperative/src/cmd/src/yargs/YargsConfigurer.ts @@ -18,8 +18,6 @@ import { ICommandDefinition } from "../doc/ICommandDefinition"; import { ICommandResponseParms } from "../doc/response/parms/ICommandResponseParms"; import { CommandProcessor } from "../CommandProcessor"; import { CommandUtils } from "../utils/CommandUtils"; -import { IProfileManagerFactory } from "../../../profiles"; -import { ICommandProfileTypeConfiguration } from "../doc/profiles/definition/ICommandProfileTypeConfiguration"; import { IHelpGeneratorFactory } from "../help/doc/IHelpGeneratorFactory"; import { ImperativeConfig } from "../../../utilities"; import { closest } from "fastest-levenshtein"; @@ -33,7 +31,6 @@ export class YargsConfigurer { constructor(private rootCommand: ICommandDefinition, private yargs: any, private commandRespParms: ICommandResponseParms, - private profileManagerFactory: IProfileManagerFactory, private helpGeneratorFactory: IHelpGeneratorFactory, private experimentalCommandDescription: string, private rootCommandName: string, @@ -43,6 +40,11 @@ export class YargsConfigurer { ) { } + public static readonly yargsConfiguration: Readonly> = { + "parse-numbers": false, + "parse-positional-numbers": false + }; + public configure() { /** @@ -53,6 +55,7 @@ export class YargsConfigurer { this.yargs.help(false); this.yargs.version(false); this.yargs.showHelpOnFail(false); + this.yargs.parserConfiguration(YargsConfigurer.yargsConfiguration); // finally, catch any undefined commands this.yargs.command({ command: "*", @@ -74,7 +77,6 @@ export class YargsConfigurer { new CommandProcessor({ definition: this.rootCommand, fullDefinition: this.rootCommand, helpGenerator: rootHelpGenerator, - profileManagerFactory: this.profileManagerFactory, rootCommandName: this.rootCommandName, commandLine: this.commandLine, envVariablePrefix: this.envVariablePrefix, @@ -108,7 +110,6 @@ export class YargsConfigurer { definition: failedCommandDefinition, fullDefinition: failedCommandDefinition, helpGenerator: rootHelpGenerator, - profileManagerFactory: this.profileManagerFactory, rootCommandName: this.rootCommandName, commandLine: ImperativeConfig.instance.commandLine, envVariablePrefix: this.envVariablePrefix, @@ -144,7 +145,6 @@ export class YargsConfigurer { definition: failedCommandDefinition, fullDefinition: failedCommandDefinition, helpGenerator: failHelpGenerator, - profileManagerFactory: this.profileManagerFactory, rootCommandName: this.rootCommandName, commandLine: this.commandLine, envVariablePrefix: this.envVariablePrefix, @@ -187,7 +187,6 @@ export class YargsConfigurer { definition: failedCommandDefinition, fullDefinition: failedCommandDefinition, helpGenerator: failHelpGenerator, - profileManagerFactory: this.profileManagerFactory, rootCommandName: this.rootCommandName, commandLine: ImperativeConfig.instance.commandLine, envVariablePrefix: this.envVariablePrefix, @@ -243,11 +242,11 @@ export class YargsConfigurer { // loop through the top level groups for (const group of this.rootCommand.children) { - if ((group.name.trim() === groupValues[0]) || (group.aliases[0] === groupValues[0])) { + if (group.name.trim() === groupValues[0] || group.aliases[0] === groupValues[0]) { groups += groupValues[0] + " "; // found the top level group so loop to see if second level group valid for (const group2 of group.children) { - if ((group2.name.trim() === groupValues[1]) || (group2.aliases[0] === groupValues[1])) { + if (group2.name.trim() === groupValues[1] || group2.aliases[0] === groupValues[1]) { groups += groupValues[1] + " "; // second level group valid so command provided is invalid, retrieve the valid command(s) for (let i = 0; i < group2.children.length; i++) { diff --git a/packages/imperative/src/cmd/src/yargs/YargsDefiner.ts b/packages/imperative/src/cmd/src/yargs/YargsDefiner.ts index f161e638d8..b6b0e6cf09 100644 --- a/packages/imperative/src/cmd/src/yargs/YargsDefiner.ts +++ b/packages/imperative/src/cmd/src/yargs/YargsDefiner.ts @@ -17,8 +17,6 @@ import { YargsCommandCompleted } from "./AbstractCommandYargs"; import { GroupCommandYargs } from "./GroupCommandYargs"; import { CommandYargs } from "./CommandYargs"; import { ICommandResponseParms } from "../../../cmd/src/doc/response/parms/ICommandResponseParms"; -import { IProfileManagerFactory } from "../../../profiles"; -import { ICommandProfileTypeConfiguration } from "../doc/profiles/definition/ICommandProfileTypeConfiguration"; import { IHelpGeneratorFactory } from "../help/doc/IHelpGeneratorFactory"; /** @@ -34,7 +32,6 @@ export class YargsDefiner { private mCommandLine: string; private mEnvVariablePrefix: string; private mHelpFactory: IHelpGeneratorFactory; - private mProfileManagerFactory: IProfileManagerFactory; private mExperimentalCommandDescription: string; private mPromptPhrase: string; @@ -47,9 +44,8 @@ export class YargsDefiner { * Build the definer - maintains the Yargs instance for all future definitions. * @param {yargs.Argv} yargsInstance: The Yargs instance used to define the commands. * @param primaryHighlightColor - main color to highlight help text headings and other text with - * @param rootCommandName - the display name of the root command (e.g. "bright" or "sample-cli") + * @param rootCommandName - the display name of the root command (e.g. "zowe" or "sample-cli") * @param envVariablePrefix - the environment variable prefix - * @param profileManagerFactory - profile manager factory that can be used to instantiate new profile managers * @param helpGeneratorFactory - help generator factory that can be used to instantiate new help generators * @param experimentalCommandDescription - optionally overridden experimental command description to * propagate to yargs services @@ -59,7 +55,6 @@ export class YargsDefiner { rootCommandName: string, commandLine: string, envVariablePrefix: string, - profileManagerFactory: IProfileManagerFactory, helpGeneratorFactory: IHelpGeneratorFactory, experimentalCommandDescription: string, promptPhrase: string) { @@ -69,7 +64,6 @@ export class YargsDefiner { this.mCommandLine = commandLine; this.mEnvVariablePrefix = envVariablePrefix; this.mHelpFactory = helpGeneratorFactory; - this.mProfileManagerFactory = profileManagerFactory; this.mExperimentalCommandDescription = experimentalCommandDescription; this.mPromptPhrase = promptPhrase; } @@ -96,7 +90,6 @@ export class YargsDefiner { commandDefinition: definition, commandResponseParms: responseParms, helpGeneratorFactory: this.mHelpFactory, - profileManagerFactory: this.mProfileManagerFactory, experimentalCommandDescription: this.mExperimentalCommandDescription, rootCommandName: this.mRootCommandName, commandLine: this.mCommandLine, @@ -110,7 +103,6 @@ export class YargsDefiner { commandDefinition: definition, commandResponseParms: responseParms, helpGeneratorFactory: this.mHelpFactory, - profileManagerFactory: this.mProfileManagerFactory, experimentalCommandDescription: this.mExperimentalCommandDescription, rootCommandName: this.mRootCommandName, commandLine: this.mCommandLine, diff --git a/packages/imperative/src/cmd/src/yargs/doc/IYargsParms.ts b/packages/imperative/src/cmd/src/yargs/doc/IYargsParms.ts index 3d1c8fb4b1..002c31394e 100644 --- a/packages/imperative/src/cmd/src/yargs/doc/IYargsParms.ts +++ b/packages/imperative/src/cmd/src/yargs/doc/IYargsParms.ts @@ -13,7 +13,6 @@ import { Argv } from "yargs"; import { ICommandDefinition } from "../../doc/ICommandDefinition"; import { GroupCommandYargs } from "../GroupCommandYargs"; import { ICommandResponseParms } from "../../doc/response/parms/ICommandResponseParms"; -import { IProfileManagerFactory } from "../../../../profiles"; import { IHelpGeneratorFactory } from "../../help/doc/IHelpGeneratorFactory"; /** @@ -48,12 +47,6 @@ export interface IYargsParms { * @memberof IYargsParms */ helpGeneratorFactory: IHelpGeneratorFactory; - /** - * The profile manager factory to use in this CLI profile management. - * @type {AbstractProfileManagerFactory} - * @memberof IYargsParms - */ - profileManagerFactory: IProfileManagerFactory; /** * Optionally override the experimental command help text block. * Used to propagate the user's configuration down to different yargs/cmd services. diff --git a/packages/imperative/src/cmd/src/yargs/doc/IYargsResponse.ts b/packages/imperative/src/cmd/src/yargs/doc/IYargsResponse.ts index f9e027376f..6d3337007f 100644 --- a/packages/imperative/src/cmd/src/yargs/doc/IYargsResponse.ts +++ b/packages/imperative/src/cmd/src/yargs/doc/IYargsResponse.ts @@ -16,7 +16,7 @@ import { ICommandResponse } from "../../../src/doc/response/response/ICommandRes export type ImperativeYargsCommandAction = "syntax validation" | "command handler invoked" | "help invoked"; /** - * The Yargs response is provided on the callback for a command definition defined through the Brightside + * The Yargs response is provided on the callback for a command definition defined through the Zowe * Yargs definer - when an execution of that command is complete - this response will be given to the callback. */ export interface IYargsResponse { diff --git a/packages/imperative/src/config/__tests__/Config.api.unit.test.ts b/packages/imperative/src/config/__tests__/Config.api.unit.test.ts index d543a981ea..af72547cbb 100644 --- a/packages/imperative/src/config/__tests__/Config.api.unit.test.ts +++ b/packages/imperative/src/config/__tests__/Config.api.unit.test.ts @@ -216,18 +216,16 @@ describe("Config API tests", () => { expect(profile).toBeNull(); }); }); - describe("expandPath", () => { + describe("getProfilePathFromName", () => { it("should expand a short proeprty path", async () => { const config = await Config.load(MY_APP); const profilePath = "lpar1.zosmf"; - // eslint-disable-next-line deprecation/deprecation - expect(config.api.profiles.expandPath(profilePath)).toEqual("profiles.lpar1.profiles.zosmf"); + expect(config.api.profiles.getProfilePathFromName(profilePath)).toEqual("profiles.lpar1.profiles.zosmf"); }); it("should expand a path with the keyword profiles", async () => { const config = await Config.load(MY_APP); const profilePath = "profiles.zosmf"; - // eslint-disable-next-line deprecation/deprecation - expect(config.api.profiles.expandPath(profilePath)).toEqual("profiles.profiles.profiles.zosmf"); + expect(config.api.profiles.getProfilePathFromName(profilePath)).toEqual("profiles.profiles.profiles.zosmf"); }); }); describe("getProfileNameFromPath", () => { @@ -570,7 +568,8 @@ describe("Config API tests", () => { describe("merge - dry run", () => { it("should merge config layers with correct priority", async () => { const config = await Config.load(MY_APP); - const existingConfig = JSONC.parse(JSONC.stringify(config.layerActive(), null, ConfigConstants.INDENT)); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + const existingConfig = JSONC.parse(JSONC.stringify(config.layerActive(), null, ConfigConstants.INDENT)) as any; const retrievedConfig = (config.api.layers.merge(mergeConfig, true) as IConfigLayer).properties; expect(retrievedConfig).toMatchSnapshot(); diff --git a/packages/imperative/src/config/__tests__/Config.secure.unit.test.ts b/packages/imperative/src/config/__tests__/Config.secure.unit.test.ts index 72b632c70a..6573aa2757 100644 --- a/packages/imperative/src/config/__tests__/Config.secure.unit.test.ts +++ b/packages/imperative/src/config/__tests__/Config.secure.unit.test.ts @@ -80,7 +80,7 @@ describe("Config secure tests", () => { config.mLayers = [ { path: "fake fakety fake", - properties: { profiles: {fake: { secure: ["fake"], properties: {fake: "fake"}}}} + properties: { profiles: { fake: { secure: ["fake"], properties: { fake: "fake" } } } } } ]; config.mVault = mockVault; @@ -137,10 +137,10 @@ describe("Config secure tests", () => { jest.spyOn(fs, "readFileSync"); let secureError: any; const vault: IConfigVault = { - load: jest.fn().mockRejectedValue(new ImperativeError({msg: "The vault failed"})), + load: jest.fn().mockRejectedValue(new ImperativeError({ msg: "The vault failed" })), save: jest.fn() }; - const config = await Config.load(MY_APP, {noLoad: true, vault: vault}); + const config = await Config.load(MY_APP, { noLoad: true, vault: vault }); config.mVault = vault; try { await config.api.secure.load(vault); @@ -167,6 +167,21 @@ describe("Config secure tests", () => { ]); }); + it("should list all secure fields for a layer", async () => { + jest.spyOn(Config, "search").mockReturnValue(projectConfigPath); + jest.spyOn(fs, "existsSync") + .mockReturnValueOnce(false) // Project user layer + .mockReturnValueOnce(true) // Project layer + .mockReturnValueOnce(false) // User layer + .mockReturnValueOnce(false); // Global layer + jest.spyOn(fs, "readFileSync"); + const config = await Config.load(MY_APP); + config.mSecure = secureConfigs; + expect(config.api.secure.securePropsForLayer(projectConfigPath)).toEqual({ [securePropPath]: "area51" }); + expect(config.api.secure.securePropsForLayer(projectUserConfigPath)).toEqual(null); + config.mSecure = {}; + }); + it("should list all secure fields for a profile", async () => { jest.spyOn(Config, "search").mockReturnValue(projectConfigPath).mockReturnValueOnce(projectUserConfigPath); jest.spyOn(fs, "existsSync") @@ -282,7 +297,7 @@ describe("Config secure tests", () => { it("rmUnusedProps should delete properties for files that do not exist", () => { const config = new (Config as any)(); - config.mSecure = {...secureConfigs}; + config.mSecure = { ...secureConfigs }; jest.spyOn(fs, "existsSync").mockReturnValueOnce(true).mockReturnValueOnce(false); const prunedFiles = config.api.secure.rmUnusedProps(); expect(prunedFiles).toEqual(["fakePath"]); diff --git a/packages/imperative/src/config/__tests__/Config.unit.test.ts b/packages/imperative/src/config/__tests__/Config.unit.test.ts index 708e480243..1ee1928519 100644 --- a/packages/imperative/src/config/__tests__/Config.unit.test.ts +++ b/packages/imperative/src/config/__tests__/Config.unit.test.ts @@ -19,6 +19,7 @@ import { ConfigConstants } from "../src/ConfigConstants"; import * as JSONC from "comment-json"; import { ConfigLayers, ConfigSecure } from "../src/api"; + const MY_APP = "my_app"; describe("Config tests", () => { diff --git a/packages/imperative/src/config/__tests__/ConfigAutoStore.unit.test.ts b/packages/imperative/src/config/__tests__/ConfigAutoStore.unit.test.ts index a861671f60..6890f5a87b 100644 --- a/packages/imperative/src/config/__tests__/ConfigAutoStore.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ConfigAutoStore.unit.test.ts @@ -10,7 +10,8 @@ */ jest.mock("../../logger/src/LoggerUtils"); -import { AbstractAuthHandler } from "../../imperative"; + +import { AbstractAuthHandler } from "../../imperative/src/auth/handlers/AbstractAuthHandler"; import { SessConstants } from "../../rest"; import { ImperativeConfig } from "../../utilities"; import { ConfigAutoStore } from "../src/ConfigAutoStore"; diff --git a/packages/imperative/src/config/__tests__/ConfigBuilder.unit.test.ts b/packages/imperative/src/config/__tests__/ConfigBuilder.unit.test.ts index f7e2f63cb5..b686927d39 100644 --- a/packages/imperative/src/config/__tests__/ConfigBuilder.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ConfigBuilder.unit.test.ts @@ -9,12 +9,14 @@ * */ -import { CredentialManagerFactory, IImperativeConfig } from "../.."; +import { IImperativeConfig } from "../.."; import { Config, ConfigBuilder, IConfig } from "../"; -import { ProfileIO } from "../../profiles"; import * as config from "../../../__tests__/__integration__/imperative/src/imperative"; import * as lodash from "lodash"; +const CHOOSE_GLOB_CONFIG = true; +const CHOOSE_PROJ_CONFIG = false; + const expectedConfigObject: IConfig = { autoStore: true, defaults: {}, @@ -68,14 +70,14 @@ describe("Config Builder tests", () => { describe("build", () => { it("should build a config without populating properties", async () => { - const builtConfig = await ConfigBuilder.build(testConfig); + const builtConfig = await ConfigBuilder.build(testConfig, CHOOSE_PROJ_CONFIG); expect(configEmptySpy).toHaveBeenCalledTimes(1); expect(getDefaultValueSpy).toHaveBeenCalledTimes(0); // Not populating any properties expect(builtConfig).toEqual(expectedConfig); }); it("should build a config and populate properties", async () => { - const builtConfig = await ConfigBuilder.build(testConfig, {populateProperties: true}); + const builtConfig = await ConfigBuilder.build(testConfig, CHOOSE_PROJ_CONFIG, {populateProperties: true}); expectedConfig.profiles.secured.properties.info = ""; expectedConfig.profiles.secured.secure.push("secret"); expectedConfig.defaults = { secured: "secured" }; @@ -86,7 +88,7 @@ describe("Config Builder tests", () => { it("should build a config and populate properties, even option with missing option definition", async () => { testConfig.profiles[0].schema.properties.fakestr = buildProfileProperty("fakestr", "string", true); - const builtConfig = await ConfigBuilder.build(testConfig, {populateProperties: true}); + const builtConfig = await ConfigBuilder.build(testConfig, CHOOSE_PROJ_CONFIG, {populateProperties: true}); expectedConfig.profiles.secured.properties.info = ""; expectedConfig.profiles.secured.properties.fakestr = ""; expectedConfig.profiles.secured.secure.push("secret"); @@ -104,7 +106,7 @@ describe("Config Builder tests", () => { testConfig.profiles[0].schema.properties.fakebool = buildProfileProperty("fakebool", "boolean"); testConfig.profiles[0].schema.properties.fakedflt = buildProfileProperty("fakedflt", "IShouldntExist"); - const builtConfig = await ConfigBuilder.build(testConfig, {populateProperties: true}); + const builtConfig = await ConfigBuilder.build(testConfig, CHOOSE_PROJ_CONFIG, {populateProperties: true}); expectedConfig.profiles.secured.properties.info = ""; expectedConfig.profiles.secured.properties.fakestr = ""; expectedConfig.profiles.secured.properties.fakenum = 0; @@ -123,7 +125,7 @@ describe("Config Builder tests", () => { it("should build a config and populate an empty property that can have multiple types", async () => { testConfig.profiles[0].schema.properties.fakestr = buildProfileProperty("fakestr", ["string", "number", "boolean"]); - const builtConfig = await ConfigBuilder.build(testConfig, {populateProperties: true}); + const builtConfig = await ConfigBuilder.build(testConfig, CHOOSE_PROJ_CONFIG, {populateProperties: true}); expectedConfig.profiles.secured.properties.info = ""; expectedConfig.profiles.secured.properties.fakestr = ""; expectedConfig.profiles.secured.secure.push("secret"); @@ -134,7 +136,7 @@ describe("Config Builder tests", () => { expect(builtConfig).toEqual(expectedConfig); }); - it("should build a config with a base profile", async () => { + it("should build a config with a project base profile", async () => { testConfig.baseProfile = { type: "base", schema: { @@ -145,7 +147,7 @@ describe("Config Builder tests", () => { } }; testConfig.profiles.push(testConfig.baseProfile); - const builtConfig = await ConfigBuilder.build(testConfig, {populateProperties: true}); + const builtConfig = await ConfigBuilder.build(testConfig, CHOOSE_PROJ_CONFIG, {populateProperties: true}); expectedConfig.profiles = { secured: { type: "secured", @@ -154,7 +156,7 @@ describe("Config Builder tests", () => { }, secure: ["secret"] }, - base: { + project_base: { type: "base", properties: { host: "" @@ -162,14 +164,14 @@ describe("Config Builder tests", () => { secure: [] } }; - expectedConfig.defaults = { base: "base", secured: "secured" }; + expectedConfig.defaults = { base: "project_base", secured: "secured" }; expect(configEmptySpy).toHaveBeenCalledTimes(1); expect(getDefaultValueSpy).toHaveBeenCalledTimes(2); // Populating default value for host and info expect(builtConfig).toEqual(expectedConfig); }); - it("should build a config with a base profile and prompt for missing property", async () => { + it("should build a config with a global base profile and prompt for missing property", async () => { testConfig.baseProfile = { type: "base", schema: { @@ -180,7 +182,7 @@ describe("Config Builder tests", () => { } }; testConfig.profiles.push(testConfig.baseProfile); - const builtConfig = await ConfigBuilder.build(testConfig, {populateProperties: true, getValueBack}); + const builtConfig = await ConfigBuilder.build(testConfig, CHOOSE_GLOB_CONFIG, {populateProperties: true, getValueBack}); expectedConfig.profiles = { secured: { type: "secured", @@ -189,7 +191,7 @@ describe("Config Builder tests", () => { }, secure: ["secret"] }, - base: { + global_base: { type: "base", properties: { host: "fake value", @@ -197,14 +199,14 @@ describe("Config Builder tests", () => { secure: [] } }; - expectedConfig.defaults = { base: "base", secured: "secured" }; + expectedConfig.defaults = { base: "global_base", secured: "secured" }; expect(configEmptySpy).toHaveBeenCalledTimes(1); expect(getDefaultValueSpy).toHaveBeenCalledTimes(2); // Populating default value for host and info expect(builtConfig).toEqual(expectedConfig); }); - it("should build a config with a base profile and prompt for missing secure property", async () => { + it("should build a config with a global base profile and prompt for missing secure property", async () => { testConfig.profiles.push(testConfig.baseProfile); expectedConfig.profiles = { secured: { @@ -214,7 +216,7 @@ describe("Config Builder tests", () => { }, secure: ["secret"] }, - base: { + global_base: { type: "base", properties: { secret: "fake value" @@ -222,11 +224,11 @@ describe("Config Builder tests", () => { secure: ["secret"] } }; - expectedConfig.defaults = { base: "base", secured: "secured" }; + expectedConfig.defaults = { base: "global_base", secured: "secured" }; let builtConfig; let caughtError; try { - builtConfig = await ConfigBuilder.build(testConfig, {populateProperties: true, getValueBack}); + builtConfig = await ConfigBuilder.build(testConfig, CHOOSE_GLOB_CONFIG, {populateProperties: true, getValueBack}); } catch (error) { caughtError = error; } @@ -236,152 +238,4 @@ describe("Config Builder tests", () => { expect(builtConfig).toEqual(expectedConfig); }); }); - - describe("convert", () => { - const mockSecureLoad = jest.fn().mockReturnValue("\"area51\""); - - beforeAll(() => { - jest.spyOn(CredentialManagerFactory, "manager", "get").mockReturnValue({ - load: mockSecureLoad - } as any); - }); - - it("should successfully convert multiple v1 profiles to config object", async () => { - jest.spyOn(ProfileIO, "getAllProfileDirectories").mockReturnValueOnce(["fruit", "nut"]); - jest.spyOn(ProfileIO, "getAllProfileNames") - .mockReturnValueOnce(["apple", "banana", "coconut"]) - .mockReturnValueOnce(["almond", "brazil", "cashew"]); - jest.spyOn(ProfileIO, "readMetaFile") - .mockReturnValueOnce({ defaultProfile: "apple" } as any) - .mockReturnValueOnce({ defaultProfile: "brazil" } as any); - jest.spyOn(ProfileIO, "readProfileFile") - .mockReturnValueOnce({ color: "green", secret: "managed by A" }) - .mockReturnValueOnce({ color: "yellow", secret: "managed by B" }) - .mockReturnValueOnce({ color: "brown", secret: "managed by C" }) - .mockReturnValueOnce({ unitPrice: 1 }) - .mockReturnValueOnce({ unitPrice: 5 }) - .mockReturnValueOnce({ unitPrice: 2 }); - const convertResult = await ConfigBuilder.convert(__dirname); - expect(convertResult.config).toMatchObject({ - profiles: { - fruit_apple: { - type: "fruit", - properties: { color: "green", secret: "area51" }, - secure: ["secret"] - }, - fruit_banana: { - type: "fruit", - properties: { color: "yellow", secret: "area51" }, - secure: ["secret"] - }, - fruit_coconut: { - type: "fruit", - properties: { color: "brown", secret: "area51" }, - secure: ["secret"] - }, - nut_almond: { - type: "nut", - properties: { unitPrice: 1 }, - secure: [] - }, - nut_brazil: { - type: "nut", - properties: { unitPrice: 5 }, - secure: [] - }, - nut_cashew: { - type: "nut", - properties: { unitPrice: 2 }, - secure: [] - } - }, - defaults: { - fruit: "fruit_apple", - nut: "nut_brazil" - }, - autoStore: true - }); - expect(Object.keys(convertResult.profilesConverted).length).toBe(2); - expect(convertResult.profilesFailed.length).toBe(0); - }); - - it("should fail to convert invalid v1 profiles to config object", async () => { - mockSecureLoad.mockReturnValueOnce(null); - const metaError = new Error("invalid meta file"); - const profileError = new Error("invalid profile file"); - jest.spyOn(ProfileIO, "getAllProfileDirectories").mockReturnValueOnce(["fruit", "nut"]); - jest.spyOn(ProfileIO, "getAllProfileNames") - .mockReturnValueOnce(["apple", "banana", "coconut"]) - .mockReturnValueOnce([]); - jest.spyOn(ProfileIO, "readMetaFile").mockImplementationOnce(() => { throw metaError; }); - jest.spyOn(ProfileIO, "readProfileFile") - .mockImplementationOnce(() => ({ color: "green", secret: "managed by A" })) - .mockImplementationOnce(() => { throw profileError; }) - .mockImplementationOnce(() => ({ color: "brown", secret: "managed by C" })); - const convertResult = await ConfigBuilder.convert(__dirname); - expect(convertResult.config).toMatchObject({ - profiles: { - fruit_apple: { - type: "fruit", - properties: { color: "green" }, - secure: [] - }, - fruit_coconut: { - type: "fruit", - properties: { color: "brown", secret: "area51" }, - secure: ["secret"] - } - }, - defaults: {}, - autoStore: true - }); - expect(Object.keys(convertResult.profilesConverted).length).toBe(1); - expect(convertResult.profilesFailed.length).toBe(2); - expect(convertResult.profilesFailed[0]).toMatchObject({ - name: "banana", - type: "fruit", - error: profileError - }); - expect(convertResult.profilesFailed[1]).toMatchObject({ - type: "fruit", - error: metaError - }); - }); - }); - - it("should convert v1 property names to v2 names", async () => { - jest.spyOn(ProfileIO, "getAllProfileDirectories").mockReturnValueOnce(["zosmf"]); - jest.spyOn(ProfileIO, "getAllProfileNames") - .mockReturnValueOnce(["LPAR1"]); - jest.spyOn(ProfileIO, "readMetaFile") - .mockReturnValueOnce({ defaultProfile: "LPAR1" } as any); - jest.spyOn(ProfileIO, "readProfileFile") - .mockReturnValueOnce({ - hostname: "should change to host", - username: "should change to user", - pass: "managed by A" - }); - - const convertResult = await ConfigBuilder.convert(__dirname); - - expect(convertResult.config).toMatchObject({ - profiles: { - zosmf_LPAR1: { - type: "zosmf", - properties: { - host: "should change to host", - user: "should change to user", - password: "area51" - }, - secure: ["password"] - } - }, - defaults: { - zosmf: "zosmf_LPAR1" - }, - autoStore: true - }); - expect(Object.keys(convertResult.profilesConverted).length).toBe(1); - expect(convertResult.profilesFailed.length).toBe(0); - }); }); diff --git a/packages/imperative/src/config/__tests__/ConfigSchema.unit.test.ts b/packages/imperative/src/config/__tests__/ConfigSchema.unit.test.ts index b0d582622e..5a01db05e1 100644 --- a/packages/imperative/src/config/__tests__/ConfigSchema.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ConfigSchema.unit.test.ts @@ -316,7 +316,7 @@ describe("Config Schema", () => { global: false, user: false, path: fakeProjPath, - properties: null, + properties: null as any, }; const spyConfigApiLayersActivate: any = jest.fn(); const spyConfigLayerActive: any = jest.fn(); @@ -416,10 +416,10 @@ describe("Config Schema", () => { it("should throw an error if the layer is unknown", () => { const mySpy = jest.spyOn((ConfigSchema as any), "_updateSchemaAll").mockReturnValue(fakeUpdatesPaths_active); - let caughtError = null; + let caughtError = new Error("NoErrorYet"); let result = null; try { - result = ConfigSchema.updateSchema({ schema: fakeSchema, layer: "fake" } as any); + result = ConfigSchema.updateSchema({ schema: fakeSchema, layer: "fake" } as any) as any; } catch (err) { caughtError = err; } @@ -499,7 +499,7 @@ describe("Config Schema", () => { describe("Helper: _All", () => { it("should update only the global layer if no other layers were found in the directory structure", () => { - jest.spyOn(Config, "search").mockReturnValue(null); + jest.spyOn(Config, "search").mockReturnValue(null as any); const spyActive = jest.spyOn((ConfigSchema as any), "_updateSchemaActive").mockReturnValue(fakeUpdatesPaths_active); const spyGlobal = jest.spyOn((ConfigSchema as any), "_updateSchemaGlobal").mockReturnValue(fakeUpdatesPaths_global); const copyHelperOptions = cloneDeep(helperOptions); @@ -515,7 +515,7 @@ describe("Config Schema", () => { }); it("should update the project and global schemas if nothing else was found in the directory structure", () => { - jest.spyOn(Config, "search").mockReturnValue(null); + jest.spyOn(Config, "search").mockReturnValue(null as any); const spyActive = jest.spyOn((ConfigSchema as any), "_updateSchemaActive").mockReturnValue(fakeUpdatesPaths_active); const spyGlobal = jest.spyOn((ConfigSchema as any), "_updateSchemaGlobal").mockReturnValue(fakeUpdatesPaths_global); @@ -529,7 +529,7 @@ describe("Config Schema", () => { }); it("should update all schemas found up the directory structure and down to the given depth", () => { - jest.spyOn(Config, "search").mockReturnValueOnce(fakeUserPath).mockReturnValueOnce(null); + jest.spyOn(Config, "search").mockReturnValueOnce(fakeUserPath).mockReturnValueOnce(null as any); const spyActive = jest.spyOn((ConfigSchema as any), "_updateSchemaActive") .mockReturnValueOnce(fakeUpdatesPaths_active) .mockReturnValueOnce(fakeUpdatesPaths_active_1) diff --git a/packages/imperative/src/config/__tests__/ConfigUtils.unit.test.ts b/packages/imperative/src/config/__tests__/ConfigUtils.unit.test.ts index 7a7abae614..f064825c66 100644 --- a/packages/imperative/src/config/__tests__/ConfigUtils.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ConfigUtils.unit.test.ts @@ -9,11 +9,21 @@ * */ +import * as fs from "fs"; +import * as path from "path"; +import * as os from "os"; +import * as jsonfile from "jsonfile"; import { ConfigUtils } from "../../config/src/ConfigUtils"; import { CredentialManagerFactory } from "../../security"; import { ImperativeConfig } from "../../utilities"; +import { EnvironmentalVariableSettings } from "../../imperative/src/env/EnvironmentalVariableSettings"; +import { IExtendersJsonOpts } from "../src/doc/IExtenderOpts"; describe("Config Utils", () => { + afterEach(() => { + jest.restoreAllMocks(); + }); + describe("coercePropValue", () => { it("should parse value when type is boolean", () => { expect(ConfigUtils.coercePropValue("false", "boolean")).toBe(false); @@ -92,4 +102,268 @@ describe("Config Utils", () => { expect(error.additionalDetails).toBe(solution); }); }); + + describe("onlyV1ProfilesExist", () => { + afterEach(() => { + jest.restoreAllMocks(); // restore spies + jest.clearAllMocks(); // set counts back to zero + }); + + it("should return false when a team config exists", () => { + jest.spyOn(ImperativeConfig, "instance", "get").mockReturnValueOnce({ + config: { + exists: true + } + } as any); + + expect(ConfigUtils.onlyV1ProfilesExist).toBe(false); + }); + + it("should return false when neither team config or v1 profiles exist", () => { + jest.spyOn(ImperativeConfig, "instance", "get").mockReturnValue({ + config: { + exists: false + }, + cliHome: "/fake/cli/home/dir", + loadedConfig: jest.fn(() => { + return { + envVariablePrefix: "Fake_cli_prefix" + }; + }) + } as any); + + const fsExistsSyncSpy = jest.spyOn(fs, "existsSync").mockReturnValueOnce(false); + + expect(ConfigUtils.onlyV1ProfilesExist).toBe(false); + expect(fsExistsSyncSpy).toHaveBeenCalledTimes(1); + }); + + it("should return true when only V1 profiles exist", () => { + jest.spyOn(ImperativeConfig, "instance", "get").mockReturnValue({ + config: { + exists: false + }, + cliHome: "/fake/cli/home/dir", + loadedConfig: jest.fn(() => { + return { + envVariablePrefix: "Fake_cli_prefix" + }; + }) + } as any); + + const fsExistsSyncSpy = jest.spyOn(fs, "existsSync").mockReturnValueOnce(true); + + expect(ConfigUtils.onlyV1ProfilesExist).toBe(true); + expect(fsExistsSyncSpy).toHaveBeenCalledTimes(1); + }); + }); + + describe("formGlobOrProjProfileNm", () => { + afterEach(() => { + /* zzz + jest.restoreAllMocks(); // restore spies + jest.clearAllMocks(); // set counts back to zero + */ + }); + + it("should return the type name if the type is not base", () => { + const baseProfileName = ConfigUtils.formGlobOrProjProfileNm("zosmf", false); + expect(baseProfileName).toEqual("zosmf"); + }); + + it("should return a project base profile name when asked", () => { + const baseProfileName = ConfigUtils.formGlobOrProjProfileNm("base", false); + expect(baseProfileName).toEqual("project_base"); + }); + + it("should return a global base profile name when asked", () => { + const baseProfileName = ConfigUtils.formGlobOrProjProfileNm("base", true); + expect(baseProfileName).toEqual("global_base"); + }); + + it("should return a global base profile name when no project layer exists", () => { + jest.spyOn(ImperativeConfig, "instance", "get").mockReturnValue({ + config: { + exists: true, + layers: [ + { + path: "fakePath", + exists: true, + properties: {}, + global: true, + user: false + } + ] + } + } as any); + + const baseProfileName = ConfigUtils.formGlobOrProjProfileNm("base"); + expect(baseProfileName).toEqual("global_base"); + }); + + it("should return a global base profile name when no base type in nested profiles", () => { + jest.spyOn(ImperativeConfig, "instance", "get").mockReturnValue({ + config: { + exists: true, + layers: [ + { + path: "fakePath", + exists: true, + properties: {}, + global: false, + user: false + } + ], + layerProfiles: jest.fn(() => { + return { + properties: {} + }; + }) + } + } as any); + + const baseProfileName = ConfigUtils.formGlobOrProjProfileNm("base"); + expect(baseProfileName).toEqual("global_base"); + }); + + it("should return a project base profile name when found in nested profiles", () => { + jest.spyOn(ImperativeConfig, "instance", "get").mockReturnValue({ + config: { + exists: true, + layers: [ + { + path: "fakePath", + exists: true, + properties: {}, + global: false, + user: false + } + ], + layerProfiles: jest.fn(() => { + return { + properties: { + profiles: { + profiles: { + properties: {}, + type: "base" + } + } + } + }; + }) + } + } as any); + + const baseProfileName = ConfigUtils.formGlobOrProjProfileNm("base"); + expect(baseProfileName).toEqual("project_base"); + }); + }); + + describe("getZoweDir", () => { + const expectedLoadedConfig = { + name: "zowe", + defaultHome: path.join("z", "zowe"), + envVariablePrefix: "ZOWE" + }; + let defaultHome: string; + let envReadSpy: any; + let homeDirSpy: any; + let loadedConfigOrig: any; + + beforeAll(() => { + loadedConfigOrig = ImperativeConfig.instance.loadedConfig; + }); + + beforeEach(() => { + envReadSpy = jest.spyOn(EnvironmentalVariableSettings, "read").mockReturnValue({ + cliHome: { value: null } + } as any); + homeDirSpy = jest.spyOn(os, "homedir").mockReturnValue(expectedLoadedConfig.defaultHome); + ImperativeConfig.instance.loadedConfig = undefined as any; + defaultHome = path.join(expectedLoadedConfig.defaultHome, ".zowe"); + }); + + afterAll(() => { + ImperativeConfig.instance.loadedConfig = loadedConfigOrig; + envReadSpy.mockRestore(); + homeDirSpy.mockRestore(); + }); + + it("should return the ENV cliHome even if loadedConfig is set in the process", () => { + jest.spyOn(EnvironmentalVariableSettings, "read").mockReturnValue({ cliHome: { value: "test" } } as any); + expect(ImperativeConfig.instance.loadedConfig).toBeUndefined(); + expect(ConfigUtils.getZoweDir()).toEqual("test"); + expect(ImperativeConfig.instance.loadedConfig).toEqual({ ...expectedLoadedConfig, defaultHome }); + }); + + it("should return the defaultHome and set loadedConfig if undefined", () => { + expect(ImperativeConfig.instance.loadedConfig).toBeUndefined(); + expect(ConfigUtils.getZoweDir()).toEqual(defaultHome); + expect(ImperativeConfig.instance.loadedConfig).toEqual({ ...expectedLoadedConfig, defaultHome }); + }); + + it("should return the defaultHome and reset loadedConfig if defaultHome changes", () => { + expect(ImperativeConfig.instance.loadedConfig).toBeUndefined(); + ImperativeConfig.instance.loadedConfig = { ...expectedLoadedConfig, defaultHome: "test" }; + expect(ImperativeConfig.instance.loadedConfig?.defaultHome).toEqual("test"); + expect(ConfigUtils.getZoweDir()).toEqual(defaultHome); + expect(ImperativeConfig.instance.loadedConfig).toEqual({ ...expectedLoadedConfig, defaultHome }); + }); + + it("should return the defaultHome without resetting loadedConfig", () => { + expect(ImperativeConfig.instance.loadedConfig).toBeUndefined(); + ImperativeConfig.instance.loadedConfig = expectedLoadedConfig; + expect(ConfigUtils.getZoweDir()).toEqual(defaultHome); + expect(ImperativeConfig.instance.loadedConfig).toEqual({ ...expectedLoadedConfig, defaultHome }); + }); + }); + + const dummyExtJson: IExtendersJsonOpts = { + profileTypes: { + "test": { + from: ["Zowe Client App"] + } + } + }; + describe("readExtendersJsonFromDisk", () => { + // case 1: the JSON file doesn't exist at time of read + it("writes an empty extenders.json file if it doesn't exist on disk", async () => { + const writeFileSyncMock = jest.spyOn(jsonfile, "writeFileSync").mockImplementation(); + jest.spyOn(fs, "existsSync").mockReturnValueOnce(false); + ConfigUtils.readExtendersJson(); + expect(writeFileSyncMock).toHaveBeenCalled(); + }); + + // case 2: JSON file exists on-disk at time of read + it("reads extenders.json from disk if it exists", async () => { + const readFileSyncMock = jest.spyOn(jsonfile, "readFileSync").mockReturnValueOnce(dummyExtJson); + jest.spyOn(fs, "existsSync").mockReturnValueOnce(true); + const result = ConfigUtils.readExtendersJson(); + expect(readFileSyncMock).toHaveBeenCalled(); + expect(result).toEqual({ + profileTypes: { + "test": { + from: ["Zowe Client App"] + } + } + }); + }); + }); + + describe("writeExtendersJson", () => { + // case 1: Write operation is successful + it("returns true if written to disk successfully", async () => { + const writeFileSyncMock = jest.spyOn(jsonfile, "writeFileSync").mockImplementation(); + expect(ConfigUtils.writeExtendersJson(dummyExtJson)).toBe(true); + expect(writeFileSyncMock).toHaveBeenCalled(); + }); + + // case 2: Write operation is unsuccessful + it("returns false if it couldn't write to disk", async () => { + const writeFileSyncMock = jest.spyOn(jsonfile, "writeFileSync").mockImplementation(); + writeFileSyncMock.mockImplementation(() => { throw new Error(); }); + expect(ConfigUtils.writeExtendersJson(dummyExtJson)).toBe(false); + expect(writeFileSyncMock).toHaveBeenCalled(); + }); + }); }); diff --git a/packages/imperative/src/config/__tests__/ConvertV1Profiles.unit.test.ts b/packages/imperative/src/config/__tests__/ConvertV1Profiles.unit.test.ts new file mode 100644 index 0000000000..a842f4e953 --- /dev/null +++ b/packages/imperative/src/config/__tests__/ConvertV1Profiles.unit.test.ts @@ -0,0 +1,1857 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +jest.mock("jsonfile"); + +import * as fs from "fs"; +import * as fsExtra from "fs-extra"; +import * as jsonfile from "jsonfile"; +import { CredentialManagerFactory } from "../.."; +import { ConvertV1Profiles } from "../"; +import { ConvertMsgFmt } from "../src/doc/IConvertV1Profiles"; +import { ImperativeConfig } from "../../utilities/src/ImperativeConfig"; +import { ImperativeError } from "../../error/src/ImperativeError"; +import { keyring } from "@zowe/secrets-for-zowe-sdk"; +import { Logger } from "../../logger/src/Logger"; +import { LoggingConfigurer } from "../../imperative/src/LoggingConfigurer"; +import { V1ProfileRead } from "../../profiles"; +import { ConfigSchema } from "../../config/src/ConfigSchema"; +import { AppSettings } from "../../settings/src/AppSettings"; +import { CredentialManagerOverride } from "../../security/src/CredentialManagerOverride"; +import { ProfileInfo } from "../src/ProfileInfo"; +import { OverridesLoader } from "../../imperative/src/OverridesLoader"; + +jest.mock("../../imperative/src/OverridesLoader"); + +describe("ConvertV1Profiles tests", () => { + const oldScsPluginNm = "@zowe/secure-credential-store-for-zowe-cli"; + const profileDir = "/fake/path/to/profiles/"; + const appName = "zowe"; + + beforeAll(() => { + // do not attempt to do any logging configuration + Logger.initLogger = jest.fn(); + LoggingConfigurer.configureLogger = jest.fn(); + }); + + beforeEach(() => { + // do not actually log any errors + jest.spyOn(Logger, "getImperativeLogger").mockReturnValue({ + error: jest.fn() + } as any); + }); + + describe("convert", () => { + let isConversionNeededSpy: any = jest.fn(); + let replaceOldCredMgrOverrideSpy: any = jest.fn(); + let initCredMgrSpy: any = jest.fn(); + let moveV1ProfilesToConfigFileSpy: any = jest.fn(); + let deleteV1ProfilesSpy: any = jest.fn(); + + beforeAll(() => { + // use "any" so that we can call private functions + isConversionNeededSpy = jest.spyOn(ConvertV1Profiles as any, "isConversionNeeded"); + replaceOldCredMgrOverrideSpy = jest.spyOn(ConvertV1Profiles as any, "replaceOldCredMgrOverride"); + initCredMgrSpy = jest.spyOn(ConvertV1Profiles as any, "initCredMgr"); + moveV1ProfilesToConfigFileSpy = jest.spyOn(ConvertV1Profiles as any, "moveV1ProfilesToConfigFile"); + deleteV1ProfilesSpy = jest.spyOn(ConvertV1Profiles as any, "deleteV1Profiles"); + + // cliHome is a getter property, so mock the property. + Object.defineProperty(ImperativeConfig.instance, "cliHome", { + configurable: true, + get: jest.fn(() => { + return "/fake/cliHome"; + }) + }); + }); + + beforeEach(() => { + // functions called by convert which we just want to confirm have been called. + replaceOldCredMgrOverrideSpy.mockReturnValue(void 0); + initCredMgrSpy.mockResolvedValue(Promise.resolve()); + moveV1ProfilesToConfigFileSpy.mockResolvedValue(Promise.resolve()); + deleteV1ProfilesSpy.mockResolvedValue(Promise.resolve()); + }); + + afterEach(() => { + jest.clearAllMocks(); // clear our spies usage counts + }); + + afterAll(() => { + // restore original app implementations + isConversionNeededSpy.mockRestore(); + replaceOldCredMgrOverrideSpy.mockRestore(); + initCredMgrSpy.mockRestore(); + moveV1ProfilesToConfigFileSpy.mockRestore(); + deleteV1ProfilesSpy.mockRestore(); + }); + + it("should complete a conversion when all utility functions work", async () => { + isConversionNeededSpy.mockReturnValueOnce(true); + + // call the function that we want to test + await ConvertV1Profiles.convert({ + deleteV1Profs: true + }); + + expect(isConversionNeededSpy).toHaveBeenCalled(); + expect(replaceOldCredMgrOverrideSpy).toHaveBeenCalled(); + expect(initCredMgrSpy).toHaveBeenCalled(); + expect(moveV1ProfilesToConfigFileSpy).toHaveBeenCalled(); + expect(deleteV1ProfilesSpy).toHaveBeenCalled(); + }); + + it("should report that CLI must uninstall plugin when called with ProfileInfo", async () => { + isConversionNeededSpy.mockReturnValueOnce(true); + + // Ensure that the old SCS plugin name is populated in the convert result + replaceOldCredMgrOverrideSpy.mockImplementation(() => { + ConvertV1Profiles["convertResult"].v1ScsPluginName = oldScsPluginNm; + }); + + // call the function that we want to test + const profInfo = new ProfileInfo(appName); + await ConvertV1Profiles.convert({ + deleteV1Profs: true, + profileInfo : profInfo + }); + + expect(isConversionNeededSpy).toHaveBeenCalled(); + expect(replaceOldCredMgrOverrideSpy).toHaveBeenCalled(); + expect(initCredMgrSpy).toHaveBeenCalled(); + expect(moveV1ProfilesToConfigFileSpy).toHaveBeenCalled(); + expect(deleteV1ProfilesSpy).toHaveBeenCalled(); + + /* The following line is a swell debug tool when a code block, + * which is trying to match lines of result messages (like the block below), + * does not get the results that it expects. + * + console.log("convertResult:\n " + JSON.stringify(ConvertV1Profiles["convertResult"], null, 2)); + */ + + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.REPORT_LINE && + nextMsg.msgText.includes( + `The obsolete plug-in ${oldScsPluginNm} should be uninstalled because the SCS is now ` + + `embedded within the Zowe clients. Zowe CLI plugins can only be uninstalled by the CLI. ` + + `Use the command 'zowe plugins uninstall ${oldScsPluginNm}'.` + ) + ) { + numMsgsFound++; + } + } + expect(numMsgsFound).toEqual(1); + }); + + it("should not delete profiles when asked not to delete", async () => { + isConversionNeededSpy.mockReturnValueOnce(true); + + // call the function that we want to test + await ConvertV1Profiles.convert({ + deleteV1Profs: false + }); + + expect(isConversionNeededSpy).toHaveBeenCalled(); + expect(replaceOldCredMgrOverrideSpy).toHaveBeenCalled(); + expect(initCredMgrSpy).toHaveBeenCalled(); + expect(moveV1ProfilesToConfigFileSpy).toHaveBeenCalled(); + expect(deleteV1ProfilesSpy).not.toHaveBeenCalled(); + }); + + it("should skip conversion and not delete profiles", async () => { + isConversionNeededSpy.mockReturnValueOnce(false); + + // call the function that we want to test + await ConvertV1Profiles.convert({ + deleteV1Profs: false + }); + + expect(isConversionNeededSpy).toHaveBeenCalled(); + expect(replaceOldCredMgrOverrideSpy).not.toHaveBeenCalled(); + expect(initCredMgrSpy).not.toHaveBeenCalled(); + expect(moveV1ProfilesToConfigFileSpy).not.toHaveBeenCalled(); + expect(deleteV1ProfilesSpy).not.toHaveBeenCalled(); + }); + + it("should skip conversion but still delete profiles", async () => { + isConversionNeededSpy.mockReturnValueOnce(false); + + // call the function that we want to test + await ConvertV1Profiles.convert({ + deleteV1Profs: true + }); + + expect(isConversionNeededSpy).toHaveBeenCalled(); + expect(replaceOldCredMgrOverrideSpy).not.toHaveBeenCalled(); + expect(initCredMgrSpy).not.toHaveBeenCalled(); + expect(moveV1ProfilesToConfigFileSpy).not.toHaveBeenCalled(); + expect(deleteV1ProfilesSpy).toHaveBeenCalled(); + }); + + it("should catch an unexpected exception", async () => { + const fakeErrMsg = "A message from a fake exception"; + isConversionNeededSpy.mockImplementation(() => { + throw new Error(fakeErrMsg); + }); + + // call the function that we want to test + await ConvertV1Profiles.convert({ + deleteV1Profs: true + }); + + expect(isConversionNeededSpy).toHaveBeenCalled(); + expect(replaceOldCredMgrOverrideSpy).not.toHaveBeenCalled(); + expect(initCredMgrSpy).not.toHaveBeenCalled(); + expect(moveV1ProfilesToConfigFileSpy).not.toHaveBeenCalled(); + expect(deleteV1ProfilesSpy).not.toHaveBeenCalled(); + + let numErrMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.ERROR_LINE && + (nextMsg.msgText.includes("Encountered the following error while trying to convert V1 profiles:") || + nextMsg.msgText.includes(fakeErrMsg))) + { + numErrMsgsFound++; + } + } + expect(numErrMsgsFound).toEqual(3); + }); + }); // end convert + + describe("private functions", () => { + let mockSecureLoad: any; + function setCredMgrState(desiredState: string): void { + if (desiredState == "works") { + mockSecureLoad = jest.fn().mockReturnValue("\"area51\""); + } else { + mockSecureLoad = jest.fn().mockReturnValue(null); + } + + jest.spyOn(CredentialManagerFactory, "manager", "get").mockReturnValue({ + load: mockSecureLoad + } as any); + } + + beforeEach(() => { + // create the result normally created by the public function convert() + ConvertV1Profiles["convertResult"] = { + msgs: [], + v1ScsPluginName: null, + credsWereMigrated: true, + cfgFilePathNm: ConvertV1Profiles["noCfgFilePathNm"], + numProfilesFound: 0, + profilesConverted: {}, + profilesFailed: [] + }; + }); + + afterEach(() => { + jest.clearAllMocks(); // clear our spies usage counts + }); + + describe("isConversionNeeded", () => { + let getOldProfileCountSpy: any; + + afterAll(() => { + getOldProfileCountSpy.mockRestore(); // restore original app implementation + }); + + it("should return false if a client config exists", async () => { + // Pretend that we have a zowe config. + Object.defineProperty(ImperativeConfig.instance, "config", { + configurable: true, + get: jest.fn(() => { + return { + exists: true + }; + }) + }); + + // call the function that we want to test + // using class["name"] notation because it is a private static function + const convNeeded = await ConvertV1Profiles["isConversionNeeded"](); + + expect(convNeeded).toEqual(false); + let numErrMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.REPORT_LINE && + nextMsg.msgText.includes( + "Did not convert any V1 profiles because a current Zowe client configuration was found" + )) + { + numErrMsgsFound++; + } + } + expect(numErrMsgsFound).toEqual(1); + }); + + it("should return false if we find no V1 profiles", async () => { + // Pretend that we have no zowe config. + Object.defineProperty(ImperativeConfig.instance, "config", { + configurable: true, + get: jest.fn(() => { + return { + exists: false + }; + }) + }); + + // pretend that we have no old V1 profiles + getOldProfileCountSpy = jest.spyOn( + ConvertV1Profiles as any, "getOldProfileCount") + .mockReturnValueOnce(0); + + // call the function that we want to test + const convNeeded = await ConvertV1Profiles["isConversionNeeded"](); + + expect(getOldProfileCountSpy).toHaveBeenCalled(); + expect(convNeeded).toEqual(false); + + let numErrMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.REPORT_LINE && + nextMsg.msgText.includes("Did not convert any V1 profiles because no V1 profiles were found") + ){ + numErrMsgsFound++; + } + } + expect(numErrMsgsFound).toEqual(1); + }); + + it("should return false if no profiles directory exists", async () => { + // Pretend that we have no zowe config. + Object.defineProperty(ImperativeConfig.instance, "config", { + configurable: true, + get: jest.fn(() => { + return { + exists: false + }; + }) + }); + + // pretend that an error occurred because the profiles directory did not exist + ConvertV1Profiles["profilesRootDir"] = profileDir; + const noDirError = new ImperativeError({ + additionalDetails: { code: 'ENOENT' } + } as any); + getOldProfileCountSpy = jest.spyOn(ConvertV1Profiles as any, "getOldProfileCount") + .mockImplementationOnce(() => { throw noDirError; }); + + // call the function that we want to test + const convNeeded = await ConvertV1Profiles["isConversionNeeded"](); + + expect(getOldProfileCountSpy).toHaveBeenCalled(); + expect(convNeeded).toEqual(false); + + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.REPORT_LINE && + nextMsg.msgText.includes(`Did not convert any V1 profiles because ` + + `no V1 profiles were found at ${profileDir}`) + ) { + numMsgsFound++; + } + } + expect(numMsgsFound).toEqual(1); + }); + + it("should return false if an IO error occurs while reading profiles", async () => { + // Pretend that we have no zowe config. + Object.defineProperty(ImperativeConfig.instance, "config", { + configurable: true, + get: jest.fn(() => { + return { + exists: false + }; + }) + }); + + // pretend that got an I/O error + ConvertV1Profiles["profilesRootDir"] = profileDir; + const ioErrMsg = "Fake I/O error occurred"; + const ioError = new ImperativeError({ + msg: ioErrMsg + }); + getOldProfileCountSpy = jest.spyOn(ConvertV1Profiles as any, "getOldProfileCount") + .mockImplementationOnce(() => { throw ioError; }); + + // call the function that we want to test + const convNeeded = await ConvertV1Profiles["isConversionNeeded"](); + + expect(getOldProfileCountSpy).toHaveBeenCalled(); + expect(convNeeded).toEqual(false); + + let numErrMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.ERROR_LINE && + ( + nextMsg.msgText.includes(`Failed to get V1 profiles in "${profileDir}"`) || + nextMsg.msgText.includes(ioErrMsg) + ) + ) { + numErrMsgsFound++; + } + } + expect(numErrMsgsFound).toEqual(2); + }); + + it("should return true if we find some V1 profiles", async () => { + // Pretend that we have no zowe config. + Object.defineProperty(ImperativeConfig.instance, "config", { + configurable: true, + get: jest.fn(() => { + return { + exists: false + }; + }) + }); + + // pretend that we have 6 old V1 profiles + getOldProfileCountSpy = jest.spyOn( + ConvertV1Profiles as any, "getOldProfileCount") + .mockReturnValueOnce(6); + + // call the function that we want to test + const convNeeded = await ConvertV1Profiles["isConversionNeeded"](); + + expect(getOldProfileCountSpy).toHaveBeenCalled(); + expect(convNeeded).toEqual(true); + }); + }); // end isConversionNeeded + + describe("moveV1ProfilesToConfigFile", () => { + let convertPropNamesSpy: any = jest.fn(); + let createNewConfigFileSpy: any = jest.fn(); + + afterAll(() => { + // restore original app implementations + convertPropNamesSpy.mockRestore(); + createNewConfigFileSpy.mockRestore(); + }); + + it("should successfully move multiple v1 profiles to a config file", async () => { + jest.spyOn(V1ProfileRead, "getAllProfileDirectories").mockReturnValueOnce(["fruit", "nut"]); + jest.spyOn(V1ProfileRead, "getAllProfileNames") + .mockReturnValueOnce(["apple", "banana", "coconut"]) + .mockReturnValueOnce(["almond", "brazil", "cashew"]); + jest.spyOn(V1ProfileRead, "readMetaFile") + .mockReturnValueOnce({ defaultProfile: "apple" } as any) + .mockReturnValueOnce({ defaultProfile: "brazil" } as any); + jest.spyOn(V1ProfileRead, "readProfileFile") + .mockReturnValueOnce({ color: "green", secret: "managed by A" }) + .mockReturnValueOnce({ color: "yellow", secret: "managed by B" }) + .mockReturnValueOnce({ color: "brown", secret: "managed by C" }) + .mockReturnValueOnce({ unitPrice: 1 }) + .mockReturnValueOnce({ unitPrice: 5 }) + .mockReturnValueOnce({ unitPrice: 2 }); + convertPropNamesSpy = jest.spyOn(ConvertV1Profiles as any, "convertPropNames") + .mockImplementation(jest.fn()); + createNewConfigFileSpy = jest.spyOn(ConvertV1Profiles as any, "createNewConfigFile") + .mockImplementation(jest.fn()); + + // Avoid using the real secure credMgr. Pretend it works. + setCredMgrState("works"); + + // call the function that we want to test + await ConvertV1Profiles["moveV1ProfilesToConfigFile"](); + + const convertResult = ConvertV1Profiles["convertResult"]; + expect(Object.keys(convertResult.profilesConverted).length).toBe(2); + expect(convertResult.profilesFailed.length).toBe(0); + + let numMsgsFound = 0; + for (const nextMsg of convertResult.msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.REPORT_LINE) { + if (nextMsg.msgText.includes("Converted fruit profiles: apple, banana, coconut") || + nextMsg.msgText.includes("Converted nut profiles: almond, brazil, cashew") + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(2); + }); + + it("should fail to convert invalid v1 profiles to config object", async () => { + const metaError = new Error("invalid meta file"); + const profileError = new Error("invalid profile file"); + jest.spyOn(V1ProfileRead, "getAllProfileDirectories").mockReturnValueOnce(["fruit", "nut"]); + jest.spyOn(V1ProfileRead, "getAllProfileNames") + .mockReturnValueOnce(["apple", "banana", "coconut"]) + .mockReturnValueOnce([]); + jest.spyOn(V1ProfileRead, "readMetaFile").mockImplementationOnce(() => { throw metaError; }); + jest.spyOn(V1ProfileRead, "readProfileFile") + .mockImplementationOnce(() => ({ color: "green", secret: "managed by A" })) + .mockImplementationOnce(() => { throw profileError; }) + .mockImplementationOnce(() => ({ color: "brown", secret: "managed by C" })); + convertPropNamesSpy = jest.spyOn(ConvertV1Profiles as any, "convertPropNames") + .mockImplementation(jest.fn()); + createNewConfigFileSpy = jest.spyOn(ConvertV1Profiles as any, "createNewConfigFile") + .mockImplementation(jest.fn()); + + // Avoid using the real secure credMgr. Pretend it fails. + setCredMgrState("fails"); + + // call the function that we want to test + await ConvertV1Profiles["moveV1ProfilesToConfigFile"](); + + const convertResult = ConvertV1Profiles["convertResult"]; + expect(Object.keys(convertResult.profilesConverted).length).toBe(1); + expect(convertResult.profilesFailed.length).toBe(2); + + let numMsgsFound = 0; + for (const nextMsg of convertResult.msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.REPORT_LINE) { + if (nextMsg.msgText.includes("Converted fruit profiles: apple, coconut")) { + numMsgsFound++; + } + } else { + if (nextMsg.msgText.includes('Failed to read "fruit" profile named "banana"') || + nextMsg.msgText.includes("invalid profile file") || + nextMsg.msgText.includes('Failed to find default "fruit" profile') || + nextMsg.msgText.includes("invalid meta file") || + nextMsg.msgText.includes("Unable to convert 2 profile(s).") + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(6); + }); + }); // end moveV1ProfilesToConfigFile + + describe("convertPropNames", () => { + it("should convert old v1 property names to new names", () => { + const testConfig= { + profiles: { + zosmf_LPAR1: { + type: "zosmf", + properties: { + hostname: "should change to host", + username: "should change to user", + pass: "should change to password" + }, + secure: ["username", "pass"] + } + }, + defaults: { + zosmf: "zosmf_LPAR1" + }, + autoStore: true + }; + + // call the function that we want to test + ConvertV1Profiles["convertPropNames"](testConfig); + + const convertedProps = testConfig.profiles.zosmf_LPAR1.properties; + expect(Object.prototype.hasOwnProperty.call(convertedProps, "hostname")).toBe(false); + expect(Object.prototype.hasOwnProperty.call(convertedProps, "host")).toBe(true); + expect(Object.prototype.hasOwnProperty.call(convertedProps, "username")).toBe(false); + expect(Object.prototype.hasOwnProperty.call(convertedProps, "user")).toBe(true); + expect(Object.prototype.hasOwnProperty.call(convertedProps, "pass")).toBe(false); + expect(Object.prototype.hasOwnProperty.call(convertedProps, "password")).toBe(true); + }); + }); // end convertPropNames + + describe("createNewConfigFile", () => { + const testConfig = { + profiles: { + zosmf_LPAR1: { + type: "zosmf", + properties: { + host: "should change to host", + user: "should change to user", + }, + secure: ["password"] + } + }, + defaults: { + zosmf: "zosmf_LPAR1" + }, + autoStore: true + }; + + let loadV1SchemasSpy: any = jest.fn(); + let updateSchemaSpy: any = jest.fn(); + let activateSpy: any; + let mergeSpy: any; + let saveSpy: any; + let layerActiveSpy: any; + + beforeAll(() => { + // Pretend that our utility functions work. + activateSpy = jest.fn(); + mergeSpy = jest.fn(); + saveSpy = jest.fn(); + layerActiveSpy = jest.fn().mockReturnValue({ + exists: false, + global: true, + user: false, + path: "/fake/path/to/config", + properties: null as any, + }); + + loadV1SchemasSpy = jest.spyOn(ConvertV1Profiles as any, "loadV1Schemas").mockReturnValue(void 0); + updateSchemaSpy = jest.spyOn(ConfigSchema, "updateSchema").mockReturnValue(0 as any); + + jest.spyOn(ImperativeConfig.instance, "config", "get").mockReturnValue({ + api: { + layers: { + activate: activateSpy, + merge: mergeSpy + } as any, + }, + layerActive: layerActiveSpy, + save: saveSpy + } as any); + }); + + beforeEach(() => { + // reset usage counts + loadV1SchemasSpy.mockClear(); + updateSchemaSpy.mockClear(); + }); + + afterAll(() => { + // restore original app implementations + loadV1SchemasSpy.mockRestore(); + updateSchemaSpy.mockRestore(); + }); + + it("should create a config file and report movement of old profiles", async () => { + // we report movement when we do not delete + ConvertV1Profiles["convertOpts"] = { + deleteV1Profs: false + }; + + // pretend that rename worked + const renameSpy = jest.spyOn(fs, "renameSync") + .mockReturnValue(0 as any); + + // call the function that we want to test + await ConvertV1Profiles["createNewConfigFile"](testConfig); + + expect(activateSpy).toHaveBeenCalled(); + expect(mergeSpy).toHaveBeenCalled(); + expect(loadV1SchemasSpy).toHaveBeenCalled(); + expect(updateSchemaSpy).toHaveBeenCalled(); + expect(saveSpy).toHaveBeenCalled(); + expect(renameSpy).toHaveBeenCalled(); + + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.REPORT_LINE) { + if (nextMsg.msgText.includes("Your old V1 profiles have been moved") && + nextMsg.msgText.includes("Delete them by re-running this operation and requesting deletion") + || + nextMsg.msgText.includes("Your new profiles have been saved") && + nextMsg.msgText.includes("To change your configuration, update that file in your text editor") + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(2); + }); + + it("should create a config file and NOT report movement of old profiles", async () => { + // we were asked to delete + ConvertV1Profiles["convertOpts"] = { + deleteV1Profs: true + }; + + // pretend that rename worked + const renameSpy = jest.spyOn(fs, "renameSync") + .mockReturnValue(0 as any); + + // call the function that we want to test + await ConvertV1Profiles["createNewConfigFile"](testConfig); + + expect(activateSpy).toHaveBeenCalled(); + expect(mergeSpy).toHaveBeenCalled(); + expect(loadV1SchemasSpy).toHaveBeenCalled(); + expect(updateSchemaSpy).toHaveBeenCalled(); + expect(saveSpy).toHaveBeenCalled(); + expect(renameSpy).toHaveBeenCalled(); + + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.REPORT_LINE) { + expect(nextMsg.msgText.includes("Your old V1 profiles have been moved")).toBe(false); + + if (nextMsg.msgText.includes("Your new profiles have been saved") && + nextMsg.msgText.includes("To change your configuration, update that file in your text editor") + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(1); + }); + + it("should create a config vault if needed", async () => { + // make the vault non-existent + const configObj = ImperativeConfig.instance.config; + configObj["mVault"] = null as any; + + // request that we do not delete profiles + ConvertV1Profiles["convertOpts"] = { + deleteV1Profs: false + }; + + // pretend that rename worked + const renameSpy = jest.spyOn(fs, "renameSync") + .mockReturnValue(0 as any); + + // call the function that we want to test + await ConvertV1Profiles["createNewConfigFile"](testConfig); + + expect(ImperativeConfig.instance.config["mVault"]).not.toEqual(null); + expect(activateSpy).toHaveBeenCalled(); + expect(mergeSpy).toHaveBeenCalled(); + expect(loadV1SchemasSpy).toHaveBeenCalled(); + expect(updateSchemaSpy).toHaveBeenCalled(); + expect(saveSpy).toHaveBeenCalled(); + expect(renameSpy).toHaveBeenCalled(); + + // prevent calling the real underlying credentialManager factory load and save functions + Object.defineProperty(CredentialManagerFactory, "manager", { + configurable: true, + get: jest.fn(() => { + return { + configurable: true, + load: jest.fn(() => { }), + save: jest.fn(() => { }) + }; + }) + }); + + // get coverage of the load and save functions of the vault + await ImperativeConfig.instance.config.mVault.load(appName); + await ImperativeConfig.instance.config.mVault.save("name", "value"); + }); + + it("should catch and report a problem when rename throws an error", async () => { + // we were asked to delete + ConvertV1Profiles["convertOpts"] = { + deleteV1Profs: true + }; + + // pretend that rename crashed + const renameError = "fs.renameSync threw a horrible error"; + const renameSpy = jest.spyOn(fs, "renameSync").mockImplementation(() => { + throw new Error(renameError); + }); + + // call the function that we want to test + let caughtErr: any; + try { + await ConvertV1Profiles["createNewConfigFile"](testConfig); + } catch (err) { + caughtErr = err; + } + + expect(caughtErr).not.toBeDefined(); + expect(activateSpy).toHaveBeenCalled(); + expect(mergeSpy).toHaveBeenCalled(); + expect(loadV1SchemasSpy).toHaveBeenCalled(); + expect(updateSchemaSpy).toHaveBeenCalled(); + expect(saveSpy).toHaveBeenCalled(); + expect(renameSpy).toHaveBeenCalled(); + + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.REPORT_LINE) { + if (nextMsg.msgText.includes("Your new profiles have been saved") && + nextMsg.msgText.includes("To change your configuration, update that file in your text editor") + ) { + numMsgsFound++; + } + } else { + if (nextMsg.msgText.includes("Failed to rename profiles directory") || + nextMsg.msgText.includes(`Reason: ${renameError}`) || + nextMsg.msgText.includes(`Error: ${renameError}`) + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(4); + }); + }); // end createNewConfigFile + + describe("putCfgFileNmInResult", () => { + + it("should use a placeholder cfgFilePathName when layerActive fails", async () => { + // Pretend layerActive crashed + jest.spyOn(ImperativeConfig.instance, "config", "get").mockReturnValue({ + api: { + layers: { + activate: jest.fn(), + merge: jest.fn(), + } as any, + }, + layerActive: jest.fn().mockImplementation(() => { + throw new Error("layerActiveCrashed"); + }), + save: jest.fn() + } as any); + + ConvertV1Profiles["convertResult"].cfgFilePathNm = null as any; + + // call the function that we want to test + ConvertV1Profiles["putCfgFileNmInResult"](null as any); + + expect(ConvertV1Profiles["convertResult"].cfgFilePathNm).toEqual(ConvertV1Profiles["noCfgFilePathNm"]); + }); + }); // end putCfgFileNmInResult + + describe("deleteV1Profiles", () => { + let isZoweKeyRingAvailableSpy: any = jest.fn(); + let findOldSecurePropsSpy: any = jest.fn(); + let deleteOldSecurePropsSpy: any = jest.fn(); + + afterAll(() => { + // restore original app implementations + isZoweKeyRingAvailableSpy.mockRestore(); + findOldSecurePropsSpy.mockRestore(); + deleteOldSecurePropsSpy.mockRestore(); + }); + + const oldProfileDir = "/fake/path/to/profiles-old"; + let existsSyncSpy: any; + let removeSyncSpy: any; + + beforeAll(() => { + ConvertV1Profiles["oldProfilesDir"] = oldProfileDir; + existsSyncSpy = jest.spyOn(fs, "existsSync"); + removeSyncSpy = jest.spyOn(fsExtra, "removeSync"); + }); + + beforeEach(() => { + // pretend that remove works + removeSyncSpy.mockReturnValue(0 as any); + + // reset usage counts + existsSyncSpy.mockClear(); + removeSyncSpy.mockClear(); + }); + + afterAll(() => { + // restore original app implementations + existsSyncSpy.mockRestore(); + removeSyncSpy.mockRestore(); + }); + + it("should delete the old v1 profiles directory", async () => { + // pretend that we found no secure property names under any old-school service + findOldSecurePropsSpy = jest.spyOn(ConvertV1Profiles as any, "findOldSecureProps") + .mockResolvedValue(Promise.resolve([])); + + // pretend that the profiles directory exists + existsSyncSpy.mockReturnValue(true); + + // call the function that we want to test + await ConvertV1Profiles["deleteV1Profiles"](); + + expect(removeSyncSpy).toHaveBeenCalled(); + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.REPORT_LINE) { + if (nextMsg.msgText.includes(`Deleted the old profiles directory ${oldProfileDir}`)) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(1); + }); + + it("should report that the old v1 profiles directory does not exist", async () => { + // pretend that we found no secure property names under any old-school service + findOldSecurePropsSpy = jest.spyOn(ConvertV1Profiles as any, "findOldSecureProps") + .mockResolvedValue(Promise.resolve([])); + + // pretend that the profiles directory not exist + existsSyncSpy.mockReturnValue(false); + + // call the function that we want to test + await ConvertV1Profiles["deleteV1Profiles"](); + + expect(removeSyncSpy).not.toHaveBeenCalled(); + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.REPORT_LINE) { + if (nextMsg.msgText.includes(`The old profiles directory ${oldProfileDir} did not exist.`)) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(1); + }); + + it("should catch and report a problem when remove throws an error", async () => { + // pretend that we found no secure property names under any old-school service + findOldSecurePropsSpy = jest.spyOn(ConvertV1Profiles as any, "findOldSecureProps") + .mockResolvedValue(Promise.resolve([])); + + // pretend that the profiles directory exists + existsSyncSpy.mockReturnValue(true); + + // pretend that remove crashed + const removeError = "fsExtra.removeSync threw a horrible error"; + removeSyncSpy.mockImplementation(() => { + throw new Error(removeError); + }); + + // call the function that we want to test + let caughtErr: any; + try { + await ConvertV1Profiles["deleteV1Profiles"](); + } catch (err) { + caughtErr = err; + } + + expect(removeSyncSpy).toHaveBeenCalled(); + expect(caughtErr).not.toBeDefined(); + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.ERROR_LINE) { + if (nextMsg.msgText.includes(`Failed to delete the profiles directory '${oldProfileDir}'`) || + nextMsg.msgText.includes(removeError) + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(2); + }); + + it("should also delete credentials stored by old SCS plugin", async () => { + // pretend that the zowe keyring is available + isZoweKeyRingAvailableSpy = jest.spyOn(ConvertV1Profiles as any, "isZoweKeyRingAvailable") + .mockResolvedValue(Promise.resolve(true)); + + // pretend that we found secure property names under one old-school service + findOldSecurePropsSpy = jest.spyOn(ConvertV1Profiles as any, "findOldSecureProps") + .mockResolvedValueOnce(Promise.resolve(["secureUser", "securePassword"])) + .mockResolvedValue(Promise.resolve([])); + + deleteOldSecurePropsSpy = jest.spyOn(ConvertV1Profiles as any, "deleteOldSecureProps") + .mockResolvedValue(Promise.resolve(true)); + + // pretend that the profiles directory exists + existsSyncSpy.mockReturnValue(true); + + // call the function that we want to test + await ConvertV1Profiles["deleteV1Profiles"](); + + expect(removeSyncSpy).toHaveBeenCalled(); + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.REPORT_LINE) { + if (nextMsg.msgText.includes("Deleted obsolete secure value ") && + ( + nextMsg.msgText.includes("secureUser") || + nextMsg.msgText.includes("securePassword") + ) + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(2); + }); + + it("should report an error when we fail to delete secure credentials", async () => { + // pretend that the zowe keyring is available + isZoweKeyRingAvailableSpy = jest.spyOn(ConvertV1Profiles as any, "isZoweKeyRingAvailable") + .mockResolvedValue(Promise.resolve(true)); + + // pretend that we found secure property names under one old-school service + findOldSecurePropsSpy = jest.spyOn(ConvertV1Profiles as any, "findOldSecureProps") + .mockResolvedValueOnce(Promise.resolve(["secureUser", "securePassword"])) + .mockResolvedValue(Promise.resolve([])); + + // pretend that secure credential deletion failed + deleteOldSecurePropsSpy = jest.spyOn(ConvertV1Profiles as any, "deleteOldSecureProps") + .mockResolvedValue(Promise.resolve(false)); + + // pretend that the profiles directory exists + existsSyncSpy.mockReturnValue(true); + + // call the function that we want to test + await ConvertV1Profiles["deleteV1Profiles"](); + + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.ERROR_LINE) { + if (nextMsg.msgText.includes("Failed to delete obsolete secure value") && + ( + nextMsg.msgText.includes("secureUser") || + nextMsg.msgText.includes("securePassword") + ) + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(2); + }); + + it("should only report directory deletion when zowe keyring is unavailable", async () => { + // pretend that the zowe keyring is unavailable + isZoweKeyRingAvailableSpy = jest.spyOn(ConvertV1Profiles as any, "isZoweKeyRingAvailable") + .mockResolvedValue(Promise.resolve(false)); + + // pretend that the profiles directory exists + existsSyncSpy.mockReturnValue(true); + + // call the function that we want to test + await ConvertV1Profiles["deleteV1Profiles"](); + + expect(removeSyncSpy).toHaveBeenCalled(); + let numDirDelMsgs = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgText.includes(`Deleted the old profiles directory ${oldProfileDir}`)) { + numDirDelMsgs++; + } + } + expect(ConvertV1Profiles["convertResult"].msgs.length).toEqual(1); + expect(numDirDelMsgs).toEqual(1); + }); + }); // end deleteV1Profiles + + describe("replaceOldCredMgrOverride", () => { + let getOldPluginInfoSpy: any; + + beforeAll(() => { + getOldPluginInfoSpy = jest.spyOn(ConvertV1Profiles as any, "getOldPluginInfo"); + }); + + afterAll(() => { + // restore original app implementations + getOldPluginInfoSpy.mockRestore(); + }); + + it("should do nothing if there are no overrides", () => { + // pretend that no overrides exist + getOldPluginInfoSpy.mockReturnValueOnce({ plugins: [], overrides: [] }); + + const appSettingsGetSpy = jest.spyOn(AppSettings, "instance", "get"); + + // call the function that we want to test + let caughtErr: any; + try { + ConvertV1Profiles["replaceOldCredMgrOverride"](); + } catch (err) { + caughtErr = err; + } + + expect(caughtErr).not.toBeDefined(); + expect(appSettingsGetSpy).not.toHaveBeenCalled(); + }); + + it("should replace a v1 SCS credential manager and report a v1 SCS plugin", async () => { + // pretend that we found an old credential manager + const fakeV1ScsPlugin = "FakeScsPlugin"; + getOldPluginInfoSpy.mockReturnValueOnce( + { plugins: [fakeV1ScsPlugin], overrides: ["CredentialManager"] } + ); + + // pretend that we set the credMgr + const appSettingsSetSpy = jest.fn(); + jest.spyOn(AppSettings, "instance", "get").mockReturnValue({ + set: appSettingsSetSpy + } as any); + + // pretend that our loadedConfig has a credMgr override + jest.spyOn(ImperativeConfig.instance, "loadedConfig", "get").mockReturnValue({ + overrides: { + CredentialManager: "CfgMgrOverride" + } + } as any); + + // call the function that we want to test + let caughtErr: any; + try { + await ConvertV1Profiles["replaceOldCredMgrOverride"](); + } catch (err) { + caughtErr = err; + } + + expect(caughtErr).not.toBeDefined(); + expect(appSettingsSetSpy).toHaveBeenCalledWith( + "overrides", "CredentialManager", CredentialManagerOverride.DEFAULT_CRED_MGR_NAME + ); + expect(ConvertV1Profiles["convertResult"].v1ScsPluginName).toEqual(fakeV1ScsPlugin); + expect(ConvertV1Profiles["convertResult"].credsWereMigrated).toEqual(true); + }); + + it("should catch and report an error thrown by AppSettings.instance.set", () => { + // pretend that we found an old credential manager + const fakeV1ScsPlugin = "FakeScsPlugin"; + getOldPluginInfoSpy.mockReturnValueOnce( + { plugins: [fakeV1ScsPlugin], overrides: ["CredentialManager"] } + ); + + // pretend that AppSettings.set() throws an exception + const appSettingsCrashErrMsg = "A fake exception from AppSettings.instance.set"; + const appSettingsSetSpy = jest.fn().mockImplementation(() => { + throw new Error(appSettingsCrashErrMsg); + }); + jest.spyOn(AppSettings, "instance", "get").mockReturnValue({ + set: appSettingsSetSpy + } as any); + + // call the function that we want to test + let caughtErr: any; + try { + ConvertV1Profiles["replaceOldCredMgrOverride"](); + } catch (err) { + caughtErr = err; + } + + expect(caughtErr).not.toBeDefined(); + expect(appSettingsSetSpy).toHaveBeenCalledWith( + "overrides", "CredentialManager", CredentialManagerOverride.DEFAULT_CRED_MGR_NAME + ); + expect(ConvertV1Profiles["convertResult"].v1ScsPluginName).toEqual(fakeV1ScsPlugin); + expect(ConvertV1Profiles["convertResult"].credsWereMigrated).toEqual(false); + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.ERROR_LINE) { + if (nextMsg.msgText.includes("Failed to replace credential manager override setting") || + nextMsg.msgText.includes(`Reason: ${appSettingsCrashErrMsg}`) || + nextMsg.msgText.includes(`Error: ${appSettingsCrashErrMsg}`) + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(3); + }); + }); // end replaceOldCredMgrOverride + + describe("getOldPluginInfo", () => { + let isPluginInstalledSpy: any; + + beforeEach(() => { + isPluginInstalledSpy = jest.spyOn(ConvertV1Profiles as any, "isPluginInstalled"); + }); + + afterAll(() => { + isPluginInstalledSpy.mockRestore(); // restore original app implementation + }); + + it("should retrieve old credMgr override and old plugin", () => { + // pretend that we find the old SCS CredMgr name + const oldScsName = "@zowe/secure-credential-store-for-zowe-cli"; + const appSettingsGetSpy = jest.fn().mockReturnValue(oldScsName); + jest.spyOn(AppSettings, "instance", "get").mockReturnValue({ + get: appSettingsGetSpy + } as any); + + // pretend that the old zowe SCS plugin is installed + isPluginInstalledSpy.mockReturnValue(true); + + // call the function that we want to test + let pluginInfo: any; + let caughtErr: any; + try { + pluginInfo = ConvertV1Profiles["getOldPluginInfo"](); + } catch (err) { + caughtErr = err; + } + + expect(caughtErr).not.toBeDefined(); + expect(appSettingsGetSpy).toHaveBeenCalled(); + + let numItemsFound = 0; + for (const nextOverride of pluginInfo.overrides) { + if (nextOverride === "CredentialManager") { + numItemsFound++; + } + } + expect(numItemsFound).toEqual(1); + + numItemsFound = 0; + for (const nextPlugin of pluginInfo.plugins) { + if (nextPlugin === oldScsName) { + numItemsFound++; + } + } + expect(numItemsFound).toEqual(1); + }); + + it("should initialize appSettings when AppSettings.instance fails", () => { + // pretend that AppSettings.instance.get crashes + const appSettingsGetSpy = jest.spyOn(AppSettings, "instance", "get").mockImplementation(() => { + throw new Error("Error does not matter"); + }); + + // pretend that the old zowe SCS plugin is installed + isPluginInstalledSpy.mockReturnValue(true); + + // call the function that we want to test + let pluginInfo: any; + let caughtErr: any; + try { + pluginInfo = ConvertV1Profiles["getOldPluginInfo"](); + } catch (err) { + caughtErr = err; + } + + expect(caughtErr).not.toBeDefined(); + expect(isPluginInstalledSpy).toHaveBeenCalled(); + expect(appSettingsGetSpy).toHaveBeenCalled(); + expect(pluginInfo.overrides.length).toEqual(0); + expect(pluginInfo.plugins.length).toEqual(1); + }); + + it("should catch exception from AppSettings.instance.get and record error", () => { + // pretend that AppSettings.instance.get crashes + const fakeErrMsg = "A fake exception from AppSettings.instance.get"; + const appSettingsGetSpy = jest.fn().mockImplementation(() => { + throw new Error(fakeErrMsg); + }); + jest.spyOn(AppSettings, "instance", "get").mockReturnValue({ + get: appSettingsGetSpy + } as any); + + // pretend that the old zowe SCS plugin is installed + isPluginInstalledSpy.mockReturnValue(true); + + // call the function that we want to test + let pluginInfo: any; + let caughtErr: any; + try { + pluginInfo = ConvertV1Profiles["getOldPluginInfo"](); + } catch (err) { + caughtErr = err; + } + + expect(caughtErr).not.toBeDefined(); + expect(appSettingsGetSpy).toHaveBeenCalled(); + expect(pluginInfo.overrides.length).toEqual(0); + expect(pluginInfo.plugins.length).toEqual(1); + + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.ERROR_LINE) { + if (nextMsg.msgText.includes("Failed trying to read 'CredentialManager' overrides.") || + nextMsg.msgText.includes(`Reason: ${fakeErrMsg}`) || + nextMsg.msgText.includes(`Error: ${fakeErrMsg}`) + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(3); + }); + + it("should catch exception from isPluginInstalled and record error", () => { + // pretend that we find the old SCS CredMgr name + const oldScsName = "@zowe/secure-credential-store-for-zowe-cli"; + const appSettingsGetSpy = jest.fn().mockReturnValue(oldScsName); + jest.spyOn(AppSettings, "instance", "get").mockReturnValue({ + get: appSettingsGetSpy + } as any); + + // pretend that isPluginInstalled throws an error + const caughtErrMsg = "isPluginInstalled threw a horrible exception"; + isPluginInstalledSpy.mockImplementation(jest.fn(() => { + throw new Error(caughtErrMsg); + })); + + // call the function that we want to test + let pluginInfo: any; + let caughtErr: any; + try { + pluginInfo = ConvertV1Profiles["getOldPluginInfo"](); + } catch (err) { + caughtErr = err; + } + + expect(caughtErr).not.toBeDefined(); + + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.ERROR_LINE) { + if (nextMsg.msgText.includes("Failed trying to get the set of installed plugins") || + nextMsg.msgText.includes(`Reason: ${caughtErrMsg}`) || + nextMsg.msgText.includes(`Error: ${caughtErrMsg}`) + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(3); + }); + }); // end getOldPluginInfo + + describe("isPluginInstalled", () => { + let readFileSyncSpy: any; + + beforeAll(() => { + readFileSyncSpy = jest.spyOn(jsonfile, "readFileSync"); + + // cliHome is a getter property, so mock the property. + Object.defineProperty(ImperativeConfig.instance, "cliHome", { + configurable: true, + get: jest.fn(() => { + return "/fake/cliHome"; + }) + }); + }); + + afterAll(() => { + readFileSyncSpy.mockRestore(); // restore original app implementation + }); + + it("should return true if plugin name is in the plugins file", () => { + // make readFileSync return some fake data + const pluginName = "FakePluginName"; + const fakePluginsJson = JSON.parse(`{ + "@zowe/secure-credential-store-for-zowe-cli": { + "package": "@zowe/secure-credential-store-for-zowe-cli@zowe-v1-lts", + "registry": "https://registry.npmjs.org/", + "version": "4.1.12" + }, + "@zowe/cics-for-zowe-cli": { + "package": "@zowe/cics-for-zowe-cli@zowe-v1-lts", + "registry": "https://registry.npmjs.org/", + "version": "4.0.11" + }, + "${pluginName}": { + "package": "@zowe/${pluginName}-for-zowe-cli@zowe-v1-lts", + "registry": "https://registry.npmjs.org/", + "version": "1.2.3" + } + }`); + readFileSyncSpy.mockImplementation(() => { + return fakePluginsJson; + }); + + // call the function that we want to test + const pluginInstResult: boolean = ConvertV1Profiles["isPluginInstalled"](pluginName); + expect(pluginInstResult).toEqual(true); + }); + + it("should return false if plugin name is NOT in the plugins file", () => { + // make readFileSync return some fake data + const fakePluginsJson = JSON.parse(`{ + "@zowe/secure-credential-store-for-zowe-cli": { + "package": "@zowe/secure-credential-store-for-zowe-cli@zowe-v1-lts", + "registry": "https://registry.npmjs.org/", + "version": "4.1.12" + }, + "@zowe/cics-for-zowe-cli": { + "package": "@zowe/cics-for-zowe-cli@zowe-v1-lts", + "registry": "https://registry.npmjs.org/", + "version": "4.0.11" + }, + "@zowe/not-your-plugin": { + "package": "@zowe/these-are-not-the-droids-you-are-looking-for@zowe-v2-lts", + "registry": "https://registry.npmjs.org/", + "version": "4.0.11" + } + }`); + readFileSyncSpy.mockImplementation(() => { + return fakePluginsJson; + }); + + // call the function that we want to test + const pluginInstResult: boolean = ConvertV1Profiles["isPluginInstalled"]("PluginNameNotInstalled"); + expect(pluginInstResult).toEqual(false); + }); + + it("should catch exception from readFileSync and record error for CLI", () => { + // pretend that readFileSync throws an error + const readFileErrMsg = "readFileSync threw some horrible exception"; + readFileSyncSpy.mockImplementation(jest.fn(() => { + throw new Error(readFileErrMsg); + })); + + // call the function that we want to test + const pluginName = "FakePluginName"; + let pluginInstResult: boolean = false; + let caughtErr: any; + try { + pluginInstResult = ConvertV1Profiles["isPluginInstalled"](pluginName); + } catch (err) { + caughtErr = err; + } + + expect(caughtErr).not.toBeDefined(); + expect(pluginInstResult).toEqual(false); + + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.ERROR_LINE) { + if (nextMsg.msgText.includes("Cannot read plugins file") && nextMsg.msgText.includes("plugins.json") ) { + numMsgsFound++; + } + if ((nextMsg.msgText.includes("Reason: ") || nextMsg.msgText.includes("Error: ")) && + nextMsg.msgText.includes(readFileErrMsg) + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(3); + }); + + it("should catch exception from readFileSync but not record error for VSCode app", () => { + // pretend that readFileSync throws an error + const readFileErrMsg = "readFileSync threw some horrible exception"; + readFileSyncSpy.mockImplementation(jest.fn(() => { + throw new Error(readFileErrMsg); + })); + + // pretend that we were called by a VSCode app + ConvertV1Profiles["profileInfo"] = new ProfileInfo(appName); + + // call the function that we want to test + const pluginName = "FakePluginName"; + let pluginInstResult: boolean = false; + let caughtErr: any; + try { + pluginInstResult = ConvertV1Profiles["isPluginInstalled"](pluginName); + } catch (err) { + caughtErr = err; + } + + expect(caughtErr).not.toBeDefined(); + expect(pluginInstResult).toEqual(false); + + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.ERROR_LINE) { + if (nextMsg.msgText.includes("Cannot read plugins file") && nextMsg.msgText.includes("plugins.json")) { + numMsgsFound++; + } + if ((nextMsg.msgText.includes("Reason: ") || nextMsg.msgText.includes("Error: ")) && + nextMsg.msgText.includes(readFileErrMsg) + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(0); + }); + }); // end isPluginInstalled + + describe("getOldProfileCount", () => { + + it("should count the profiles for each profile directory", () => { + // pretend we found 3 profile directories + jest.spyOn(V1ProfileRead as any, "getAllProfileDirectories") + .mockReturnValue(["base", "zosmf", "ssh"]); + + // pretend we found 3 profile names for each directory + jest.spyOn(V1ProfileRead as any, "getAllProfileNames") + .mockReturnValueOnce(["baseName1", "baseName2", "baseName3"]) + .mockReturnValueOnce(["zosmfName1", "zosmfName2", "zosmfName3"]) + .mockReturnValueOnce(["sshName1", "sshName2", "sshName3"]); + + // call the function that we want to test + const profileCount = ConvertV1Profiles["getOldProfileCount"]("/fake/profile/root/dir"); + expect(profileCount).toEqual(9); + }); + }); // end getOldProfileCount + + describe("initCredMgr", () => { + let readProfilesFromDiskSpy: any = jest.fn(); + + beforeEach(() => { + // Reset the messages that have been reported + ConvertV1Profiles["convertResult"].msgs = []; + }); + + afterEach(() => { + jest.clearAllMocks(); // clear the mock counters + }); + + afterAll(() => { + // restore original app implementations + readProfilesFromDiskSpy.mockRestore(); + }); + + it("should detect when credMgr has already been initialized", async () => { + // change logger spy to record the message + let logMsg: string = "Nothing logged"; + jest.spyOn(Logger, "getImperativeLogger").mockImplementation(() => { + return { + error: jest.fn((errMsg) => { + logMsg = errMsg; + }) + } as any; + }); + + // pretend that credMgr has been initialized. + let initializedWasCalled = false; + Object.defineProperty(CredentialManagerFactory, "initialized", { + configurable: true, + get: jest.fn(() => { + initializedWasCalled = true; + return true; + }) + }); + + // pretend that the SCS plugin was configured as the credMgr + ConvertV1Profiles["oldScsPluginWasConfigured"] = true; + + // call the function that we want to test + await ConvertV1Profiles["initCredMgr"](); + + expect(initializedWasCalled).toEqual(true); + expect(logMsg).toContain( + `Credential manager has already been initialized with the old SCS plugin ${oldScsPluginNm}. ` + + `Old credentials cannot be migrated` + ); + }); + + it("should read profiles from disk when ProfileInfo is supplied", async () => { + // pretend that credMgr has NOT been initialized. + Object.defineProperty(CredentialManagerFactory, "initialized", { + configurable: true, + get: jest.fn(() => { + return false; + }) + }); + + // pretend that the SCS plugin was configured as the credMgr + ConvertV1Profiles["oldScsPluginWasConfigured"] = true; + + // pretend that our caller supplied ProfileInfo + ConvertV1Profiles["profileInfo"] = new ProfileInfo(appName); + + // do not actually read any ProfileInfo from disk + readProfilesFromDiskSpy = jest.spyOn(ConvertV1Profiles["profileInfo"], + "readProfilesFromDisk").mockResolvedValue(Promise.resolve()); + + // call the function that we want to test + await ConvertV1Profiles["initCredMgr"](); + expect(readProfilesFromDiskSpy).toHaveBeenCalled(); + }); + + it("should call overridesLoader when ProfileInfo is NOT supplied", async () => { + // pretend that credMgr has NOT been initialized. + Object.defineProperty(CredentialManagerFactory, "initialized", { + configurable: true, + get: jest.fn(() => { + return false; + }) + }); + + // do not actually load the overrides + ConvertV1Profiles["profileInfo"] = null as any; + const overridesLoaderSpy = jest.spyOn(OverridesLoader, "load"); + + // call the function that we want to test + await ConvertV1Profiles["initCredMgr"](); + expect(overridesLoaderSpy).toHaveBeenCalled(); + }); + + it("should catch an exception and report the error", async () => { + // pretend that credMgr has NOT been initialized. + Object.defineProperty(CredentialManagerFactory, "initialized", { + configurable: true, + get: jest.fn(() => { + return false; + }) + }); + + // do not actually read any ProfileInfo from disk + ConvertV1Profiles["profileInfo"] = new ProfileInfo(appName); + const fakeErrMsg = "A fake exception from findCredentials"; + readProfilesFromDiskSpy = jest.spyOn(ConvertV1Profiles["profileInfo"], "readProfilesFromDisk") + .mockImplementation(() => { + throw new Error(fakeErrMsg); + }); + + // call the function that we want to test + let caughtErr: any; + try { + await ConvertV1Profiles["initCredMgr"](); + } catch (err) { + caughtErr = err; + } + + expect(readProfilesFromDiskSpy).toHaveBeenCalled(); + expect(caughtErr).not.toBeDefined(); + + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.ERROR_LINE) { + if (nextMsg.msgText.includes(`Failed to initialize CredentialManager`) || + nextMsg.msgText.includes(`Reason: ${fakeErrMsg}`) || + nextMsg.msgText.includes(`Error: ${fakeErrMsg}`) + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(3); + }); + }); // end initCredMgr + + describe("loadV1Schemas", () => { + let existsSyncSpy: any; + + beforeAll(() => { + existsSyncSpy = jest.spyOn(fs, "existsSync"); + }); + + beforeEach(() => { + existsSyncSpy.mockClear(); // reset usage counts + + // pretend that our loadedConfig has no schemas in it + jest.spyOn(ImperativeConfig.instance, "loadedConfig", "get").mockReturnValue({} as any); + }); + + afterAll(() => { + // restore original app implementations + existsSyncSpy.mockRestore(); + }); + + it("should load schemas when none exist in ImperativeConfig loadedConfig", () => { + // pretend that the profiles root directory and schema file (xxx_meta.yaml) exist + existsSyncSpy.mockReturnValue(true); + + // pretend that we have profiles and they have schemas + const getAllProfileDirectoriesSpy = jest.spyOn(V1ProfileRead, "getAllProfileDirectories") + .mockReturnValue(["base", "cics", "zosmf"]); + + const readMetaFileSpy = jest.spyOn(V1ProfileRead, "readMetaFile") + .mockReturnValueOnce({ defaultProfile: "base", configuration: "baseSchema" as any }) + .mockReturnValueOnce({ defaultProfile: "cics", configuration: "cicsSchema" as any }) + .mockReturnValueOnce({ defaultProfile: "zosmf", configuration: "zosmfSchema" as any}); + + // call the function that we want to test + ConvertV1Profiles["loadV1Schemas"](); + + expect(existsSyncSpy).toHaveBeenCalled(); + expect(getAllProfileDirectoriesSpy).toHaveBeenCalledTimes(1); + expect(readMetaFileSpy).toHaveBeenCalledTimes(3); + expect(ImperativeConfig.instance.loadedConfig.profiles).toEqual(["baseSchema", "cicsSchema", "zosmfSchema"]); + }); + + it("should catch and report error thrown by readMetaFile", () => { + // pretend that the profiles root directory and schema file (xxx_meta.yaml) exist + existsSyncSpy.mockReturnValue(true); + + // pretend that we have profiles and they have schemas + const getAllProfileDirectoriesSpy = jest.spyOn(V1ProfileRead, "getAllProfileDirectories") + .mockReturnValue(["base", "cics", "zosmf"]); + + const fakeErrMsg = "A fake exception from readMetaFile"; + const readMetaFileSpy = jest.spyOn(V1ProfileRead, "readMetaFile").mockImplementation(() => { + throw new Error(fakeErrMsg); + }); + + // call the function that we want to test + let caughtErr: any; + try { + ConvertV1Profiles["loadV1Schemas"](); + } catch (err) { + caughtErr = err; + } + + expect(caughtErr).not.toBeDefined(); + expect(existsSyncSpy).toHaveBeenCalled(); + expect(getAllProfileDirectoriesSpy).toHaveBeenCalled(); + expect(readMetaFileSpy).toHaveBeenCalledTimes(3); + + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.ERROR_LINE) { + if (nextMsg.msgText.includes("Failed to load schema for profile type base") || + nextMsg.msgText.includes("Failed to load schema for profile type cics") || + nextMsg.msgText.includes("Failed to load schema for profile type zosmf") + ) { + numMsgsFound++; + } + if (nextMsg.msgText.includes(`Reason: ${fakeErrMsg}`) || + nextMsg.msgText.includes(`Error: ${fakeErrMsg}`) + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(9); + + }); + }); // end loadV1Schemas + + describe("isZoweKeyRingAvailable", () => { + + it("should return true if it finds credentials in the vault", async () => { + // pretend that findCredentials found a bunch of accounts and passwords + const findCredentialsSpy = jest.spyOn(keyring as any, "findCredentials").mockResolvedValue([ + { account: "account1", password: "password1" }, + { account: "account2", password: "password2" }, + { account: "account3", password: "password3" }, + { account: "account4", password: "password4" }, + ]); + const origZoweKeyRing = ConvertV1Profiles["zoweKeyRing"]; + ConvertV1Profiles["zoweKeyRing"] = { + findCredentials: findCredentialsSpy + } as any; + + // call the function that we want to test + const result = await ConvertV1Profiles["isZoweKeyRingAvailable"](); + + ConvertV1Profiles["zoweKeyRing"] = origZoweKeyRing; + expect(findCredentialsSpy).toHaveBeenCalledWith("@zowe/cli"); + expect(result).toEqual(true); + }); + + it("should return false if findCredentials throws an error", async () => { + // pretend that AppSettings.instance.set throws an exception + const fakeErrMsg = "A fake exception from findCredentials"; + const findCredentialsSpy = jest.spyOn(keyring as any, "findCredentials").mockImplementation(() => { + throw new Error(fakeErrMsg); + }); + const origZoweKeyRing = ConvertV1Profiles["zoweKeyRing"]; + ConvertV1Profiles["zoweKeyRing"] = { + findCredentials: findCredentialsSpy + } as any; + + // call the function that we want to test + let caughtErr: any; + let checkKeyRingResult: boolean = true; + try { + checkKeyRingResult = await ConvertV1Profiles["isZoweKeyRingAvailable"](); + } catch (err) { + caughtErr = err; + } + + ConvertV1Profiles["zoweKeyRing"] = origZoweKeyRing; + expect(findCredentialsSpy).toHaveBeenCalledWith("@zowe/cli"); + expect(caughtErr).not.toBeDefined(); + expect(checkKeyRingResult).toEqual(false); + }); + }); // end isZoweKeyRingAvailable + + describe("findOldSecureProps", () => { + + it("should find old secure properties", async () => { + // pretend that findCredentials found a bunch of accounts and passwords + const origZoweKeyRing = ConvertV1Profiles["zoweKeyRing"]; + ConvertV1Profiles["zoweKeyRing"] = { + findCredentials: jest.fn().mockResolvedValue([ + { account: "account1", password: "password1" }, + { account: "account2", password: "password2" }, + { account: "account3", password: "password3" }, + { account: "account4", password: "password4" } + ]) + } as any; + + // call the function that we want to test + const oldSecurePropNames = await ConvertV1Profiles["findOldSecureProps"]("ServiceNameDoesNotMatter"); + + ConvertV1Profiles["zoweKeyRing"] = origZoweKeyRing; + expect(oldSecurePropNames).toContain("account1"); + expect(oldSecurePropNames).toContain("account2"); + expect(oldSecurePropNames).toContain("account3"); + expect(oldSecurePropNames).toContain("account4"); + }); + + it("should catch an exception thrown by findCredentials and report the error", async () => { + // pretend that findCredentials throws an error + const origZoweKeyRing = ConvertV1Profiles["zoweKeyRing"]; + const fakeFindCredError = "findCredentials threw a horrible error"; + ConvertV1Profiles["zoweKeyRing"] = { + findCredentials: jest.fn().mockRejectedValue(new Error(fakeFindCredError)) + } as any; + + // call the function that we want to test + const fakeServiceName = "ServiceNameDoesNotMatter"; + let caughtErr: any; + try { + await ConvertV1Profiles["findOldSecureProps"](fakeServiceName); + } catch (err) { + caughtErr = err; + } + + expect(caughtErr).not.toBeDefined(); + + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.ERROR_LINE) { + if (nextMsg.msgText.includes(`Encountered an error while gathering secure properties ` + + `for service '${fakeServiceName}':`) || + nextMsg.msgText.includes(`Reason: ${fakeFindCredError}`) || + nextMsg.msgText.includes(`Error: ${fakeFindCredError}`) + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(3); + ConvertV1Profiles["zoweKeyRing"] = origZoweKeyRing; + }); + }); // end findOldSecureProps + + describe("deleteOldSecureProps", () => { + + it("should delete the specified secure property", async () => { + // pretend that we successfully deleted the secure property + ConvertV1Profiles["zoweKeyRing"] = { + deletePassword: jest.fn().mockResolvedValue(true) + } as any; + + // call the function that we want to test + const didWeDelete = await ConvertV1Profiles["deleteOldSecureProps"]("FakeAcct", "FakeProp"); + expect(didWeDelete).toBe(true); + }); + + it("should catch exception thrown by deletePassword and report the error", async () => { + // pretend that deletePassword threw an error + const origZoweKeyRing = ConvertV1Profiles["zoweKeyRing"]; + const fakeDelPassError = "deletePassword threw a horrible error"; + ConvertV1Profiles["zoweKeyRing"] = { + deletePassword: jest.fn().mockRejectedValue(new Error(fakeDelPassError)) + } as any; + + // call the function that we want to test + const fakeAcct = "FakeAccount"; + const fakeProp = "FakePropName"; + let caughtErr: any; + try { + await ConvertV1Profiles["deleteOldSecureProps"](fakeAcct, fakeProp); + } catch (err) { + caughtErr = err; + } + + expect(caughtErr).not.toBeDefined(); + + let numMsgsFound = 0; + for (const nextMsg of ConvertV1Profiles["convertResult"].msgs) { + if (nextMsg.msgFormat & ConvertMsgFmt.ERROR_LINE) { + if (nextMsg.msgText.includes( + `Encountered an error while deleting secure data for ` + + `service '${fakeAcct}/${fakeProp}':`) || + nextMsg.msgText.includes(`Reason: ${fakeDelPassError}`) || + nextMsg.msgText.includes(`Error: ${fakeDelPassError}`) + ) { + numMsgsFound++; + } + } + } + expect(numMsgsFound).toEqual(3); + ConvertV1Profiles["zoweKeyRing"] = origZoweKeyRing; + }); + }); // end deleteOldSecureProps + }); // end private functions +}); diff --git a/packages/imperative/src/config/__tests__/ProfileCredentials.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileCredentials.unit.test.ts index c0eb7c0ab6..5b0db2f8cf 100644 --- a/packages/imperative/src/config/__tests__/ProfileCredentials.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileCredentials.unit.test.ts @@ -32,7 +32,6 @@ describe("ProfileCredentials tests", () => { describe("isSecured", () => { it("should be true if team config is not secure but CredentialManager is set", () => { const profCreds = new ProfileCredentials({ - usingTeamConfig: true, getTeamConfig: () => mockConfigApi({ secureFields: () => [] }) } as any); jest.spyOn(profCreds as any, "isCredentialManagerInAppSettings").mockReturnValueOnce(true); @@ -41,7 +40,6 @@ describe("ProfileCredentials tests", () => { it("should be true if team config is secure but CredentialManager is not set", () => { const profCreds = new ProfileCredentials({ - usingTeamConfig: true, getTeamConfig: () => mockConfigApi({ secureFields: () => ["myAwesomeProperty"] }) } as any); jest.spyOn(profCreds as any, "isCredentialManagerInAppSettings").mockReturnValueOnce(false); @@ -50,33 +48,14 @@ describe("ProfileCredentials tests", () => { it("should be false if team config is not secure and CredentialManager is not set", () => { const profCreds = new ProfileCredentials({ - usingTeamConfig: true, getTeamConfig: () => mockConfigApi({ secureFields: () => [] }) } as any); jest.spyOn(profCreds as any, "isCredentialManagerInAppSettings").mockReturnValueOnce(false); expect(profCreds.isSecured).toBe(false); }); - it("should be true for old school profiles if CredentialManager is set", () => { - const profCreds = new ProfileCredentials({ - usingTeamConfig: false - } as any); - jest.spyOn(profCreds as any, "isCredentialManagerInAppSettings").mockReturnValueOnce(true); - expect(profCreds.isSecured).toBe(true); - }); - - it("should be false for old school profiles if CredentialManager is not set", () => { - const profCreds = new ProfileCredentials({ - usingTeamConfig: false - } as any); - jest.spyOn(profCreds as any, "isCredentialManagerInAppSettings").mockReturnValueOnce(false); - expect(profCreds.isSecured).toBe(false); - }); - it("should not be cached for subsequent calls", () => { - const profCreds = new ProfileCredentials({ - usingTeamConfig: true - } as any); + const profCreds = new ProfileCredentials({} as any); jest.spyOn(profCreds as any, "isTeamConfigSecure").mockReturnValueOnce(false).mockReturnValueOnce(true); expect(profCreds.isSecured).toBe(false); // expect a 2nd time to ensure value has changed @@ -106,7 +85,10 @@ describe("ProfileCredentials tests", () => { it("should initialize CredentialManagerFactory once with good credential manager", async () => { const profCreds = new ProfileCredentials({ - usingTeamConfig: false + getTeamConfig: () => mockConfigApi({ + secureFields: () => [], + load: jest.fn() + }) } as any); jest.spyOn(profCreds, "isSecured", "get").mockReturnValue(true); jest.spyOn(CredentialManagerFactory, "initialize").mockImplementation(async () => { @@ -129,9 +111,7 @@ describe("ProfileCredentials tests", () => { }); it("should fail to initialize CredentialManagerFactory with bad credential manager", async () => { - const profCreds = new ProfileCredentials({ - usingTeamConfig: false - } as any); + const profCreds = new ProfileCredentials({} as any); jest.spyOn(profCreds, "isSecured", "get").mockReturnValue(true); jest.spyOn(CredentialManagerFactory, "initialize").mockImplementation(async () => { throw new Error("bad credential manager"); @@ -164,7 +144,10 @@ describe("ProfileCredentials tests", () => { } }; const profCreds = new ProfileCredentials({ - usingTeamConfig: false + getTeamConfig: () => mockConfigApi({ + secureFields: () => ["myAwesomeProperty"], + load: jest.fn() + }), } as any, { credMgrOverride }); jest.spyOn(profCreds, "isSecured", "get").mockReturnValue(true); jest.spyOn(CredentialManagerFactory, "initialize").mockImplementation(async (params: ICredentialManagerInit) => { @@ -183,109 +166,10 @@ describe("ProfileCredentials tests", () => { expect(mockCredMgrInitialize).toHaveBeenCalledTimes(1); }); - it("should load Keytar using custom require method", async () => { - const requireKeytar = jest.fn(() => "fakeModule"); - const profCreds = new ProfileCredentials({ - usingTeamConfig: false - } as any, { - credMgrOverride: ProfileCredentials.defaultCredMgrWithKeytar(requireKeytar as any) - }); - jest.spyOn(profCreds, "isSecured", "get").mockReturnValue(true); - jest.spyOn(CredentialManagerFactory, "initialize").mockImplementation(async (params: ICredentialManagerInit) => { - await new (params.Manager as typeof DefaultCredentialManager)(params.service, params.displayName).initialize(); - }); - let caughtError; - - try { - await profCreds.loadManager(); - } catch (error) { - caughtError = error; - } - - expect(caughtError).toBeUndefined(); - expect(CredentialManagerFactory.initialize).toHaveBeenCalledTimes(1); - expect(requireKeytar).toHaveBeenCalledTimes(1); - }); - - it("should fail to load Keytar if custom require method throws", async () => { - const requireKeytar = jest.fn(() => { - throw new Error("keytar not found"); - }); - const profCreds = new ProfileCredentials({ - usingTeamConfig: false - } as any, { - credMgrOverride: ProfileCredentials.defaultCredMgrWithKeytar(requireKeytar as any) - }); - jest.spyOn(profCreds, "isSecured", "get").mockReturnValue(true); - jest.spyOn(CredentialManagerFactory, "initialize").mockImplementation(async (params: ICredentialManagerInit) => { - await new (params.Manager as typeof DefaultCredentialManager)(params.service, params.displayName).initialize(); - }); - let caughtError; - - try { - await profCreds.loadManager(); - } catch (error) { - caughtError = error; - } - - expect(caughtError).toBeDefined(); - expect(caughtError.message).toMatch(/^Failed to load Keytar module:/); - expect(CredentialManagerFactory.initialize).toHaveBeenCalledTimes(1); - expect(requireKeytar).toHaveBeenCalledTimes(1); - }); - - it("should load Keytar using custom require method - deprecated", async () => { - const requireKeytar = jest.fn(() => "fakeModule"); - const profCreds = new ProfileCredentials({ - usingTeamConfig: false - } as any, requireKeytar as any); - jest.spyOn(profCreds, "isSecured", "get").mockReturnValue(true); - jest.spyOn(CredentialManagerFactory, "initialize").mockImplementation(async (params: ICredentialManagerInit) => { - await new (params.Manager as any)(null).initialize(); - }); - let caughtError; - - try { - await profCreds.loadManager(); - } catch (error) { - caughtError = error; - } - - expect(caughtError).toBeUndefined(); - expect(CredentialManagerFactory.initialize).toHaveBeenCalledTimes(1); - expect(requireKeytar).toHaveBeenCalledTimes(1); - }); - - it("should fail to load Keytar if custom require method throws - deprecated", async () => { - const requireKeytar = jest.fn(() => { - throw new Error("keytar not found"); - }); - const profCreds = new ProfileCredentials({ - usingTeamConfig: false - } as any, requireKeytar as any); - jest.spyOn(profCreds, "isSecured", "get").mockReturnValue(true); - jest.spyOn(CredentialManagerFactory, "initialize").mockImplementation(async (params: ICredentialManagerInit) => { - await new (params.Manager as any)(null).initialize(); - }); - let caughtError; - - try { - await profCreds.loadManager(); - } catch (error) { - caughtError = error; - } - - expect(caughtError).toBeDefined(); - expect(caughtError.message).toMatch(/^Failed to load Keytar module:/); - expect(CredentialManagerFactory.initialize).toHaveBeenCalledTimes(1); - expect(requireKeytar).toHaveBeenCalledTimes(1); - }); - it("should call Config secure load API when team config enabled", async () => { const mockSecureLoad = jest.fn(); const profCreds = new ProfileCredentials({ - getTeamConfig: () => mockConfigApi({ load: mockSecureLoad }), - usingTeamConfig: true + getTeamConfig: () => mockConfigApi({ load: mockSecureLoad }) } as any); jest.spyOn(profCreds, "isSecured", "get").mockReturnValue(true); jest.spyOn(CredentialManagerFactory, "initialize").mockImplementation(); diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.OldProfiles.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.OldProfiles.unit.test.ts deleted file mode 100644 index d73f69e081..0000000000 --- a/packages/imperative/src/config/__tests__/ProfileInfo.OldProfiles.unit.test.ts +++ /dev/null @@ -1,561 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import * as path from "path"; -import { ProfileInfo } from "../src/ProfileInfo"; -import { IProfAttrs } from "../src/doc/IProfAttrs"; -import { IProfOpts } from "../src/doc/IProfOpts"; -import { ProfInfoErr } from "../src/ProfInfoErr"; -import { ProfLocType } from "../src/doc/IProfLoc"; -import { IProfileSchema, ProfileIO } from "../../profiles"; -import { ImperativeError } from "../../error"; -import { IProfArgAttrs } from "../src/doc/IProfArgAttrs"; - -const testAppNm = "ProfInfoApp"; -const testEnvPrefix = testAppNm.toUpperCase(); -const profileTypes = ["zosmf", "tso", "base", "dummy"]; - -function createNewProfInfo(newDir: string, opts?: IProfOpts): ProfileInfo { - // create a new ProfileInfo in the desired directory - process.chdir(newDir); - const profInfo = new ProfileInfo(testAppNm, opts); - jest.spyOn((profInfo as any).mCredentials, "isSecured", "get").mockReturnValue(false); - return profInfo; -} - -describe("Old-school ProfileInfo tests", () => { - - const tsoName = "tsoProfName"; - const testDir = path.join(__dirname, "__resources__"); - const homeDirPath = path.join(testDir, testAppNm + "_home"); - const homeDirPathTwo = path.join(testDir, testAppNm + "_home_two"); - const homeDirPathThree = path.join(testDir, testAppNm + "_home_three"); - const four = 4; - let origDir: string; - - beforeAll(() => { - // remember our original directory - origDir = process.cwd(); - }); - - beforeEach(() => { - // set our desired app home directory into the environment - process.env[testEnvPrefix + "_CLI_HOME"] = homeDirPath; - }); - - afterAll(() => { - // ensure that jest reports go to the right place - process.chdir(origDir); - }); - - afterEach(() => { - jest.restoreAllMocks(); - }); - - describe("getDefaultProfile", () => { - - afterEach(() => { - jest.clearAllMocks(); - }); - - it("should return null if no default for that type exists 1", async () => { - const profInfo = createNewProfInfo(homeDirPath); - const warnSpy = jest.spyOn((profInfo as any).mImpLogger, "warn"); - await profInfo.readProfilesFromDisk(); - const profAttrs = profInfo.getDefaultProfile("ThisTypeDoesNotExist"); - expect(profAttrs).toBeNull(); - expect(warnSpy).toHaveBeenCalledTimes(2); - expect(warnSpy).toHaveBeenCalledWith("Found no old-school profile for type 'ThisTypeDoesNotExist'."); - }); - - it("should return null if no default for that type exists 2", async () => { - process.env[testEnvPrefix + "_CLI_HOME"] = homeDirPathTwo; - const profInfo = createNewProfInfo(homeDirPathTwo); - const warnSpy = jest.spyOn((profInfo as any).mImpLogger, "warn"); - await profInfo.readProfilesFromDisk(); - const profAttrs = profInfo.getDefaultProfile("zosmf"); - expect(profAttrs).toBeNull(); - expect(warnSpy).toHaveBeenCalledTimes(four); - expect(warnSpy).toHaveBeenLastCalledWith("Found no default old-school profiles."); - }); - - it("should return null if no default for that type exists 3", async () => { - process.env[testEnvPrefix + "_CLI_HOME"] = homeDirPathThree; - const profInfo = createNewProfInfo(homeDirPathThree); - const warnSpy = jest.spyOn((profInfo as any).mImpLogger, "warn"); - await profInfo.readProfilesFromDisk(); - const profAttrs = profInfo.getDefaultProfile("zosmf"); - expect(profAttrs).toBeNull(); - expect(warnSpy).toHaveBeenCalledTimes(four); - expect(warnSpy).toHaveBeenLastCalledWith("Found no old-school profiles."); - }); - - it("should return null if profile root dir does not exist", async () => { - const invalidHomeDir = homeDirPath + "_does_not_exist"; - process.env[testEnvPrefix + "_CLI_HOME"] = invalidHomeDir; - const profInfo = new ProfileInfo(testAppNm); - jest.spyOn((profInfo as any).mCredentials, "isSecured", "get").mockReturnValue(false); - await profInfo.readProfilesFromDisk(); - expect(profInfo.getDefaultProfile("zosmf")).toBeNull(); - }); - - it("should return a profile if one exists", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const desiredProfType = "tso"; - const profAttrs = profInfo.getDefaultProfile(desiredProfType) as IProfAttrs; - - expect(profAttrs).not.toBeNull(); - expect(profAttrs.isDefaultProfile).toBe(true); - expect(profAttrs.profName).toBe(tsoName); - expect(profAttrs.profType).toBe(desiredProfType); - expect(profAttrs.profLoc.locType).not.toBeNull(); - - const retrievedOsLoc = path.normalize(profAttrs.profLoc.osLoc[0]); - const expectedOsLoc = path.join(homeDirPath, "profiles", - desiredProfType, profAttrs.profName + ".yaml" - ); - expect(retrievedOsLoc).toBe(expectedOsLoc); - - expect(profAttrs.profLoc.jsonLoc).toBeUndefined(); - }); - }); - - describe("getAllProfiles", () => { - it("should return all profiles if no type is specified", async () => { - const length = 8; - const expectedDefaultProfileNameZosmf = "lpar1_zosmf"; - const expectedDefaultProfileNameTso = "tsoProfName"; - const expectedDefaultProfileNameBase = "base_for_userNm"; - const expectedDefaultProfiles = 3; - let expectedProfileNames = ["lpar1_zosmf", "lpar2_zosmf", "lpar3_zosmf", "lpar4_zosmf", "lpar5_zosmf", "tsoProfName", - "base_for_userNm", "base_apiml"]; - let actualDefaultProfiles = 0; - - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const profAttrs = profInfo.getAllProfiles(); - - expect(profAttrs.length).toEqual(length); - for (const prof of profAttrs) { - if (prof.isDefaultProfile) { - let expectedName = ""; - switch (prof.profType) { - case "zosmf": expectedName = expectedDefaultProfileNameZosmf; break; - case "tso": expectedName = expectedDefaultProfileNameTso; break; - case "base": expectedName = expectedDefaultProfileNameBase; break; - } - expect(prof.profName).toEqual(expectedName); - actualDefaultProfiles += 1; - } - expect(expectedProfileNames).toContain(prof.profName); - expect(profileTypes).toContain(prof.profType); - expect(prof.profLoc.locType).toEqual(ProfLocType.OLD_PROFILE); - expect(prof.profLoc.osLoc).toBeDefined(); - expect(prof.profLoc.osLoc.length).toEqual(1); - expect(prof.profLoc.osLoc[0]).toEqual(path.join(homeDirPath, "profiles", prof.profType, prof.profName + ".yaml")); - expectedProfileNames = expectedProfileNames.filter(obj => obj !== prof.profName); - } - expect(actualDefaultProfiles).toEqual(expectedDefaultProfiles); - expect(expectedProfileNames.length).toEqual(0); - }); - - it("should return some profiles if a type is specified", async () => { - const length = 5; - const expectedName = "lpar1_zosmf"; - const expectedDefaultProfiles = 1; - const desiredProfType = "zosmf"; - let expectedProfileNames = ["lpar1_zosmf", "lpar2_zosmf", "lpar3_zosmf", "lpar4_zosmf", "lpar5_zosmf"]; - let actualDefaultProfiles = 0; - - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const profAttrs = profInfo.getAllProfiles(desiredProfType); - - expect(profAttrs.length).toEqual(length); - for (const prof of profAttrs) { - if (prof.isDefaultProfile) { - expect(prof.profName).toEqual(expectedName); - actualDefaultProfiles += 1; - } - expect(expectedProfileNames).toContain(prof.profName); - expect(profileTypes).toContain(prof.profType); - expect(prof.profLoc.locType).toEqual(ProfLocType.OLD_PROFILE); - expect(prof.profLoc.osLoc).toBeDefined(); - expect(prof.profLoc.osLoc.length).toEqual(1); - expect(prof.profLoc.osLoc[0]).toEqual(path.join(homeDirPath, "profiles", prof.profType, prof.profName + ".yaml")); - expectedProfileNames = expectedProfileNames.filter(obj => obj !== prof.profName); - } - expect(actualDefaultProfiles).toEqual(expectedDefaultProfiles); - expect(expectedProfileNames.length).toEqual(0); - }); - }); - - describe("mergeArgsForProfile", () => { - const profSchema: Partial = { - properties: { - host: { type: "string" }, - user: { - type: "string", - optionDefinition: { defaultValue: "admin" } - } as any, - password: { - type: "string", - optionDefinition: { defaultValue: "admin" } - } as any - } - }; - - const requiredProfSchema: Partial = { - properties: { - ...profSchema.properties, - protocol: { type: "string" } - }, - required: ["protocol"] - }; - - it("should find known args in simple service profile", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const profAttrs = profInfo.getDefaultProfile("zosmf") as IProfAttrs; - delete (profInfo as any).mOldSchoolProfileDefaults.base; - const mergedArgs = profInfo.mergeArgsForProfile(profAttrs); - - const expectedArgs = [ - { argName: "host", dataType: "string" }, - { argName: "port", dataType: "number" }, - { argName: "user", dataType: "string" }, - { argName: "password", dataType: "string" }, - { argName: "rejectUnauthorized", dataType: "boolean" } - ]; - - expect(mergedArgs.knownArgs.length).toBe(expectedArgs.length); - for (const [idx, arg] of mergedArgs.knownArgs.entries()) { - expect(arg).toMatchObject(expectedArgs[idx]); - expect(arg.secure || arg.argValue).toBeDefined(); - expect(arg.argLoc.locType).toBe(ProfLocType.OLD_PROFILE); - expect(arg.argLoc.osLoc[0]).toMatch(/lpar1_zosmf\.yaml$/); - } - }); - - it("should find known args in service and base profile", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const profAttrs = profInfo.getDefaultProfile("zosmf") as IProfAttrs; - (profInfo as any).mOldSchoolProfileDefaults.base = "base_apiml"; - const mergedArgs = profInfo.mergeArgsForProfile(profAttrs); - - const expectedArgs = [ - { argName: "host", dataType: "string" }, - { argName: "port", dataType: "number" }, - { argName: "user", dataType: "string" }, - { argName: "password", dataType: "string" }, - { argName: "rejectUnauthorized", dataType: "boolean" }, - { argName: "tokenType", dataType: "string" }, - { argName: "tokenValue", dataType: "string" } - ]; - - expect(mergedArgs.knownArgs.length).toBe(expectedArgs.length); - for (const [idx, arg] of mergedArgs.knownArgs.entries()) { - expect(arg).toMatchObject(expectedArgs[idx]); - expect(arg.secure || arg.argValue).toBeDefined(); - expect(arg.argLoc.locType).toBe(ProfLocType.OLD_PROFILE); - expect(arg.argLoc.osLoc[0]).toMatch(/(base_apiml|lpar1_zosmf)\.yaml$/); - } - }); - - it("should find known args defined with kebab case names", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const profAttrs = profInfo.getAllProfiles("zosmf").find(obj => obj.profName === "lpar2_zosmf"); - delete (profInfo as any).mOldSchoolProfileDefaults.base; - const mergedArgs = profInfo.mergeArgsForProfile(profAttrs as IProfAttrs); - - const expectedArgs = [ - { argName: "host", dataType: "string" }, - { argName: "port", dataType: "number" }, - { argName: "user", dataType: "string" }, - { argName: "password", dataType: "string" }, - { argName: "rejectUnauthorized", dataType: "boolean" } - ]; - - expect(mergedArgs.knownArgs.length).toBe(expectedArgs.length); - for (const [idx, arg] of mergedArgs.knownArgs.entries()) { - expect(arg).toMatchObject(expectedArgs[idx]); - expect(arg.secure || arg.argValue).toBeDefined(); - expect(arg.argLoc.locType).toBe(ProfLocType.OLD_PROFILE); - expect(arg.argLoc.osLoc[0]).toMatch(/lpar2_zosmf\.yaml$/); - } - }); - - it("should list optional args missing in service profile", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const profAttrs = profInfo.getAllProfiles("zosmf").find(obj => obj.profName === "lpar3_zosmf"); - delete (profInfo as any).mOldSchoolProfileDefaults.base; - jest.spyOn(profInfo as any, "loadSchema").mockReturnValue(profSchema); - const mergedArgs = profInfo.mergeArgsForProfile(profAttrs as IProfAttrs); - - const expectedArgs = [ - { argName: "user", dataType: "string", argValue: "admin" }, - { argName: "password", dataType: "string", argValue: "admin" } - ]; - - expect(mergedArgs.missingArgs.length).toBe(expectedArgs.length); - for (const [idx, arg] of mergedArgs.missingArgs.entries()) { - expect(arg).toMatchObject(expectedArgs[idx]); - expect(arg.argLoc.locType).toBe(ProfLocType.DEFAULT); - expect(arg.argLoc.osLoc).toBeUndefined(); - } - }); - - it("should throw if there are required args missing in service profile", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const profAttrs = profInfo.getDefaultProfile("zosmf") as IProfAttrs; - jest.spyOn(profInfo as any, "loadSchema").mockReturnValue(requiredProfSchema); - - let caughtError; - try { - profInfo.mergeArgsForProfile(profAttrs); - } catch (error) { - expect(error instanceof ProfInfoErr).toBe(true); - caughtError = error; - } - - expect(caughtError).toBeDefined(); - expect(caughtError.errorCode).toBe(ProfInfoErr.MISSING_REQ_PROP); - expect(caughtError.message).toContain("Missing required properties: protocol"); - }); - - it("should validate profile for missing args when schema exists", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const profAttrs = profInfo.getAllProfiles("zosmf").find(obj => obj.profName === "lpar3_zosmf"); - delete (profInfo as any).mOldSchoolProfileDefaults.base; - const mergedArgs = profInfo.mergeArgsForProfile(profAttrs as IProfAttrs); - - const expectedArgs = [ - { argName: "user", dataType: "string" }, - { argName: "password", dataType: "string" }, - { argName: "basePath", dataType: "string" } - ]; - - expect(mergedArgs.missingArgs.length).toBe(expectedArgs.length); - for (const [idx, arg] of mergedArgs.missingArgs.entries()) { - expect(arg).toMatchObject(expectedArgs[idx]); - expect(arg.argLoc.locType).toBe(ProfLocType.DEFAULT); - expect(arg.argLoc.osLoc).toBeUndefined(); - } - }); - - it("should throw if schema fails to load", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const profAttrs = profInfo.getDefaultProfile("zosmf") as IProfAttrs; - jest.spyOn(profInfo as any, "loadSchema").mockReturnValueOnce(null); - let caughtError; - - try { - profInfo.mergeArgsForProfile(profAttrs); - } catch (error) { - expect(error instanceof ProfInfoErr).toBe(true); - caughtError = error; - } - - expect(caughtError).toBeDefined(); - expect(caughtError.errorCode).toBe(ProfInfoErr.LOAD_SCHEMA_FAILED); - expect(caughtError.message).toContain("Failed to load schema for profile type zosmf"); - }); - - it("should throw if profile attributes are undefined", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const profAttrs = profInfo.getDefaultProfile("missing") as IProfAttrs; - let caughtError; - - try { - profInfo.mergeArgsForProfile(profAttrs); - } catch (error) { - expect(error instanceof ImperativeError).toBe(true); - caughtError = error; - } - - expect(caughtError).toBeDefined(); - expect(caughtError.message).toContain("Profile attributes must be defined"); - }); - }); - - describe("mergeArgsForProfileType", () => { - it("should find known args in base profile", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - jest.spyOn(profInfo as any, "loadSchema").mockReturnValueOnce({}); - const mergedArgs = profInfo.mergeArgsForProfileType("cics"); - - const expectedArgs = [ - { argName: "user", dataType: "string" }, - { argName: "password", dataType: "string" }, - { argName: "rejectUnauthorized", dataType: "boolean" } - ]; - - expect(mergedArgs.knownArgs.length).toBe(expectedArgs.length); - for (const [idx, arg] of mergedArgs.knownArgs.entries()) { - expect(arg).toMatchObject(expectedArgs[idx]); - expect(arg.argValue).toBeDefined(); - expect(arg.argLoc.locType).toBe(ProfLocType.OLD_PROFILE); - expect(arg.argLoc.osLoc[0]).toMatch(/base_for_userNm\.yaml$/); - } - }); - }); - - describe("loadAllSchemas", () => { - it("should load schema for profile type that does not exist", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - let caughtError; - - try { - (profInfo as any).loadAllSchemas(); - } catch (error) { - caughtError = error; - } - - expect(caughtError).toBeUndefined(); - expect((profInfo as any).mProfileSchemaCache.size).toBe(4); - }); - - it("should throw when schema file is invalid", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - jest.spyOn(ProfileIO, "readMetaFile").mockImplementationOnce(() => { - throw new Error("bad meta"); - }); - let caughtError; - - try { - (profInfo as any).loadAllSchemas(); - } catch (error) { - expect(error instanceof ProfInfoErr).toBe(true); - caughtError = error; - } - - expect(caughtError).toBeDefined(); - expect(caughtError.errorCode).toBe(ProfInfoErr.LOAD_SCHEMA_FAILED); - expect(caughtError.message).toContain("Failed to load schema for profile type"); - expect(caughtError.message).toContain("invalid meta file"); - }); - }); - - describe("updateProperty and updateKnownProperty", () => { - it("should succeed if the property is known", async () => { - const testProf = "lpar4_zosmf"; - const testHost = "lpar4.fakehost.com"; - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const before = profInfo.mergeArgsForProfile((profInfo.getAllProfiles("zosmf").find(v => v.profName === testProf)) as IProfAttrs); - await profInfo.updateProperty({ profileName: testProf, profileType: "zosmf", property: "host", value: "example.com" }); - const after = profInfo.mergeArgsForProfile((profInfo.getAllProfiles("zosmf").find(v => v.profName === testProf)) as IProfAttrs); - - expect(before.knownArgs.find(v => v.argName === "host").argValue).toEqual(testHost); - expect(after.knownArgs.find(v => v.argName === "host").argValue).toEqual("example.com"); - - await profInfo.updateProperty({ profileName: testProf, profileType: "zosmf", property: "host", value: testHost }); - const afterTests = profInfo.mergeArgsForProfile((profInfo.getAllProfiles("zosmf").find(v => v.profName === testProf)) as IProfAttrs); - expect(afterTests.knownArgs.find(v => v.argName === "host").argValue).toEqual(testHost); - }); - - it("should add a new property if it does not exist in the profile then remove it if undefined is specified", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const testProf = "lpar4_zosmf"; - const before = profInfo.mergeArgsForProfile((profInfo.getAllProfiles("zosmf").find(v => v.profName === testProf)) as IProfAttrs); - await profInfo.updateProperty({ profileName: testProf, profileType: "zosmf", property: "dummy", value: "example.com" }); - const after = profInfo.mergeArgsForProfile((profInfo.getAllProfiles("zosmf").find(v => v.profName === testProf)) as IProfAttrs); - - expect(before.knownArgs.find(v => v.argName === "dummy")).toBeUndefined(); - expect(after.knownArgs.find(v => v.argName === "dummy").argValue).toEqual("example.com"); - - await profInfo.updateProperty({ profileName: testProf, profileType: "zosmf", property: "dummy", value: undefined }); - const removed = profInfo.mergeArgsForProfile((profInfo.getAllProfiles("zosmf").find(v => v.profName === testProf)) as IProfAttrs); - expect(removed.knownArgs.find(v => v.argName === "dummy")).toBeUndefined(); - }); - }); - - describe("removeKnownProperty oldProfile tests", () => { - it("should remove property", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const testProf = "lpar4_zosmf"; - await profInfo.updateProperty({ profileName: testProf, profileType: "zosmf", property: "dummy", value: "example.com"}); - const afterUpdate = profInfo.mergeArgsForProfile((profInfo.getAllProfiles("zosmf").find(v => v.profName === testProf)) as IProfAttrs); - - await profInfo.removeKnownProperty({mergedArgs: afterUpdate, property: 'dummy'}); - const afterRemove = profInfo.mergeArgsForProfile((profInfo.getAllProfiles("zosmf").find(v => v.profName === testProf)) as IProfAttrs); - - expect(afterUpdate.knownArgs.find(v => v.argName === "dummy")?.argValue).toEqual("example.com"); - expect(afterRemove.knownArgs.find(v => v.argName === "dummy")).toBeUndefined(); - }); - }); - - describe("loadSecureArg", () => { - it("should load secure args from old school profiles", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const profAttrs = profInfo.getDefaultProfile("zosmf") as IProfAttrs; - const mergedArgs = profInfo.mergeArgsForProfile(profAttrs); - - const userArg = mergedArgs.knownArgs.find((arg) => arg.argName === "user"); - expect(userArg.argValue).toBeUndefined(); - expect(profInfo.loadSecureArg(userArg as IProfArgAttrs)).toBe("someUser"); - - const passwordArg = mergedArgs.knownArgs.find((arg) => arg.argName === "password"); - expect(passwordArg.argValue).toBeUndefined(); - expect(profInfo.loadSecureArg(passwordArg as IProfArgAttrs)).toBe("somePassword"); - }); - - it("should get secure values with mergeArgsForProfile:getSecureVals for old school profiles", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const profAttrs = profInfo.getDefaultProfile("zosmf") as IProfAttrs; - const mergedArgs = profInfo.mergeArgsForProfile(profAttrs, { getSecureVals: true }); - - const userArg = mergedArgs.knownArgs.find((arg) => arg.argName === "user"); - expect(userArg.argValue).toBe("someUser"); - - const passwordArg = mergedArgs.knownArgs.find((arg) => arg.argName === "password"); - expect(passwordArg.argValue).toBe("somePassword"); - }); - }); - - describe("getOsLocInfo", () => { - it("should return undefined if no osLoc is present", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const prof = { profName: "test", profLoc: { locType: 0 }, profType: "test", isDefaultProfile: false }; - expect(profInfo.getOsLocInfo(prof)).toBeUndefined(); - expect(profInfo.getOsLocInfo({...prof, profLoc: {locType: 0, osLoc: []}})).toBeUndefined(); - }); - - it("should return basic osLoc information for a regular v1 profile", async () => { - const profInfo = createNewProfInfo(homeDirPath); - await profInfo.readProfilesFromDisk(); - const profAttrs = profInfo.getDefaultProfile("zosmf") as IProfAttrs; - const osLocInfo = profInfo.getOsLocInfo(profAttrs); - expect(osLocInfo).toBeDefined(); - expect(osLocInfo.length).toBe(1); - expect(osLocInfo[0].name).toEqual(profAttrs.profName); - expect(osLocInfo[0].path).toEqual(profAttrs.profLoc.osLoc[0]); - expect(osLocInfo[0].user).toBeUndefined(); - expect(osLocInfo[0].global).toBeUndefined(); - }); - }); -}); diff --git a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts index d41900dfb1..420972d432 100644 --- a/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts +++ b/packages/imperative/src/config/__tests__/ProfileInfo.TeamConfig.unit.test.ts @@ -31,11 +31,13 @@ import { ConfigUtils } from "../src/ConfigUtils"; import { ConfigProfiles } from "../src/api"; import { IExtendersJsonOpts } from "../src/doc/IExtenderOpts"; import { ConfigSchema } from "../src/ConfigSchema"; -import { Logger } from "../.."; +import { Logger } from "../../logger/src/Logger"; const testAppNm = "ProfInfoApp"; const testEnvPrefix = testAppNm.toUpperCase(); const profileTypes = ["zosmf", "tso", "base", "dummy"]; +const testDir = path.join(__dirname, "__resources__"); +const teamProjDir = path.join(testDir, testAppNm + "_team_config_proj"); function createNewProfInfo(newDir: string, opts?: IProfOpts): ProfileInfo { // create a new ProfileInfo in the desired directory @@ -50,8 +52,6 @@ describe("TeamConfig ProfileInfo tests", () => { const tsoName = "tsoProfName"; const tsoProfName = "LPAR1.tsoProfName"; const tsoJsonLoc = "profiles.LPAR1.profiles." + tsoName; - const testDir = path.join(__dirname, "__resources__"); - const teamProjDir = path.join(testDir, testAppNm + "_team_config_proj"); const userTeamProjDir = path.join(testDir, testAppNm + "_user_and_team_config_proj"); const teamHomeProjDir = path.join(testDir, testAppNm + "_home_team_config_proj"); const largeTeamProjDir = path.join(testDir, testAppNm + "_large_team_config_proj"); @@ -137,6 +137,17 @@ describe("TeamConfig ProfileInfo tests", () => { expect(profLoaded.profile.profLoc.jsonLoc).toBe(profAttrs.profLoc.jsonLoc); expect(profLoaded.profile.isDefaultProfile).toBe(profAttrs.isDefaultProfile); }); + + it("should detect that only V1 profiles exist", async () => { + // onlyV1ProfilesExist is a getter of a property, so mock the property + Object.defineProperty(ConfigUtils, "onlyV1ProfilesExist", { + configurable: true, + get: jest.fn(() => { + return true; + }) + }); + expect(ProfileInfo.onlyV1ProfilesExist).toBe(true); + }); }); describe("createSession", () => { @@ -257,7 +268,6 @@ describe("TeamConfig ProfileInfo tests", () => { "getTeamConfig", "mergeArgsForProfile", "mergeArgsForProfileType", - "usingTeamConfig", "getOsLocInfo", "loadSecureArg" ]; @@ -280,7 +290,6 @@ describe("TeamConfig ProfileInfo tests", () => { const profInfo = createNewProfInfo(teamProjDir); await profInfo.readProfilesFromDisk(); - expect(profInfo.usingTeamConfig).toBe(true); const teamConfig: Config = profInfo.getTeamConfig(); expect(teamConfig).not.toBeNull(); expect(teamConfig.exists).toBe(true); @@ -293,7 +302,6 @@ describe("TeamConfig ProfileInfo tests", () => { const teamCfgOpts: IConfigOpts = { projectDir: teamProjDir }; await profInfo.readProfilesFromDisk(teamCfgOpts); - expect(profInfo.usingTeamConfig).toBe(true); const teamConfig: Config = profInfo.getTeamConfig(); expect(teamConfig).not.toBeNull(); expect(teamConfig.exists).toBe(true); @@ -322,7 +330,7 @@ describe("TeamConfig ProfileInfo tests", () => { it("should return true if credentials are not secure", async () => { // ensure that we are not in the team project directory const profInfo = createNewProfInfo(origDir); - (profInfo as any).mCredentials = {isSecured: false}; + (profInfo as any).mCredentials = { isSecured: false }; const response = await profInfo.profileManagerWillLoad(); expect(response).toEqual(true); }); @@ -357,6 +365,56 @@ describe("TeamConfig ProfileInfo tests", () => { }); }); + describe("secureFieldsWithDetails", () => { + it("should return an empty array if there are no secure fields in the given layer or if the layer does not exist", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk(); + + // Temporarily assume that there are no secure properties for this test only + profInfo.getTeamConfig().mLayers[1].properties.profiles["LPAR007"].secure = []; + + // Project User does not exist + expect(profInfo.secureFieldsWithDetails({ user: true, global: false })).toEqual([]); + + // Project Team dos exist, but has no secure properties + expect(profInfo.secureFieldsWithDetails({ user: false, global: false })).toEqual([]); + }); + + it("should return secure fields for the active layer even if they have no secure values stored in the vault", async () => { + const profInfo = createNewProfInfo(teamProjDir); + await profInfo.readProfilesFromDisk(); + + const securePropPath = "profiles.LPAR007.properties."; + const teamProjDirJson = path.join(teamProjDir, testAppNm + ".config.json"); + profInfo.getTeamConfig().mSecure = { + [teamProjDirJson]: { + [securePropPath + "string"]: "area51", + [securePropPath + "boolean"]: true, + [securePropPath + "number"]: 1234, + }, + }; + + const getPropAttr = (name: string | any, value: any, type?: string | null): IProfArgAttrs => ({ + argLoc: { osLoc: [teamProjDirJson], locType: 1, jsonLoc: securePropPath + name }, + argName: name, + argValue: value, + dataType: type !== undefined ? type : name, + }); + + expect(profInfo.secureFieldsWithDetails()).toEqual([ + getPropAttr("string", "area51"), + getPropAttr("boolean", true), + getPropAttr("number", 1234), + getPropAttr("missing-after-this", undefined, null), + getPropAttr("host", undefined, "string"), + getPropAttr("port", undefined, "number"), + getPropAttr("rejectUnauthorized", undefined, "boolean"), + ]); + + profInfo.getTeamConfig().mSecure = {}; + }); + }); + describe("getAllProfiles", () => { it("should return all profiles if no type is specified", async () => { const expectedDefaultProfiles = 4; @@ -366,7 +424,7 @@ describe("TeamConfig ProfileInfo tests", () => { const expectedDefaultProfileNameDummy = "LPAR4"; let actualDefaultProfiles = 0; let expectedProfileNames = ["LPAR1", "LPAR2", "LPAR3", "LPAR1.tsoProfName", "LPAR1.tsoProfName.tsoSubProfName", - "base_glob", "LPAR4", "LPAR5"]; + "base_glob", "LPAR4", "LPAR5", "LPAR007"]; const profInfo = createNewProfInfo(teamProjDir); await profInfo.readProfilesFromDisk(); @@ -406,7 +464,7 @@ describe("TeamConfig ProfileInfo tests", () => { const desiredProfType = "zosmf"; const expectedName = "LPAR1"; const expectedDefaultProfiles = 1; - let expectedProfileNames = ["LPAR1", "LPAR2", "LPAR3", "LPAR2_home", "LPAR5"]; + let expectedProfileNames = ["LPAR1", "LPAR2", "LPAR3", "LPAR2_home", "LPAR5", "LPAR007"]; let actualDefaultProfiles = 0; const profInfo = createNewProfInfo(teamProjDir); @@ -440,7 +498,7 @@ describe("TeamConfig ProfileInfo tests", () => { const desiredProfType = "zosmf"; const expectedName = "LPAR1"; const expectedDefaultProfiles = 1; - let expectedProfileNames = ["LPAR1", "LPAR2", "LPAR3", "LPAR5"]; + let expectedProfileNames = ["LPAR1", "LPAR2", "LPAR3", "LPAR5", "LPAR007"]; let actualDefaultProfiles = 0; const profInfo = createNewProfInfo(teamProjDir); @@ -471,6 +529,9 @@ describe("TeamConfig ProfileInfo tests", () => { }); describe("mergeArgsForProfile", () => { + beforeEach(() => { + (ImperativeConfig as any).mInstance = null; + }); afterEach(() => { delete process.env[envHost]; delete process.env[envPort]; @@ -848,6 +909,7 @@ describe("TeamConfig ProfileInfo tests", () => { it("should not look for secure properties in the global-layer base profile if it does not exist", async () => { process.env[testEnvPrefix + "_CLI_HOME"] = nestedTeamProjDir; const profInfo = createNewProfInfo(userTeamProjDir); + process.env[testEnvPrefix + "_CLI_HOME"] = nestedTeamProjDir; await profInfo.readProfilesFromDisk(); const profiles = profInfo.getAllProfiles(); const desiredProfile = "TEST001.first"; @@ -862,7 +924,7 @@ describe("TeamConfig ProfileInfo tests", () => { } expect(unexpectedError).toBeUndefined(); } else { - expect("Profile " + desiredProfile + "not found").toBeUndefined(); + expect("Profile " + desiredProfile + " not found").toBeUndefined(); } expect(mergedArgs.missingArgs.find(a => a.argName === "user")?.secure).toBeTruthy(); expect(mergedArgs.missingArgs.find(a => a.argName === "password")?.secure).toBeTruthy(); @@ -935,6 +997,9 @@ describe("TeamConfig ProfileInfo tests", () => { describe("loadSchema", () => { it("should return null if schema is not found", () => { const profInfo = createNewProfInfo(teamProjDir); + profInfo["mLoadedConfig"] = { + mLayers: [] + } as any; let schema: IProfileSchema; let caughtError; @@ -1100,7 +1165,7 @@ describe("TeamConfig ProfileInfo tests", () => { expect(storeSpy).toHaveBeenCalledWith({ config: profInfo.getTeamConfig(), profileName: "LPAR4", profileType: "dummy", defaultBaseProfileName: "base_glob", - propsToStore: [ "DOES_NOT_EXIST" ], sessCfg: { "DOES_NOT_EXIST": true }, setSecure : undefined, + propsToStore: ["DOES_NOT_EXIST"], sessCfg: { "DOES_NOT_EXIST": true }, setSecure: undefined, }); }); @@ -1139,7 +1204,7 @@ describe("TeamConfig ProfileInfo tests", () => { const storageSpy = jest.spyOn(ConfigAutoStore as any, "_storeSessCfgProps").mockResolvedValue(undefined); const profiles = [{ type: "test", schema: {} as any }]; ImperativeConfig.instance.loadedConfig.profiles = profiles; - ImperativeConfig.instance.loadedConfig.baseProfile = null; + ImperativeConfig.instance.loadedConfig.baseProfile = undefined; let caughtError; try { @@ -1180,7 +1245,7 @@ describe("TeamConfig ProfileInfo tests", () => { expect(storeSpy).toHaveBeenCalledWith({ config: profInfo.getTeamConfig(), profileName: "typeless", profileType: null, defaultBaseProfileName: "base_glob", - propsToStore: [ "areBirdsReal" ], sessCfg: { "areBirdsReal": true }, setSecure : undefined, + propsToStore: ["areBirdsReal"], sessCfg: { "areBirdsReal": true }, setSecure: undefined, }); }); @@ -1226,7 +1291,7 @@ describe("TeamConfig ProfileInfo tests", () => { expect(storeSpy).toHaveBeenCalledWith({ config: profInfo.getTeamConfig(), profileName: "typeless_new", profileType: null, defaultBaseProfileName: "base_glob", - propsToStore: [ "areBirdsReal" ], sessCfg: { "areBirdsReal": true }, setSecure : undefined, + propsToStore: ["areBirdsReal"], sessCfg: { "areBirdsReal": true }, setSecure: undefined, }); }); }); @@ -1339,11 +1404,11 @@ describe("TeamConfig ProfileInfo tests", () => { const mergedArgs = profInfo.mergeArgsForProfile(profAttrs); const userArg = mergedArgs.knownArgs.find((arg) => arg.argName === "user"); - expect(userArg.argValue).toBe("userNameBase"); + expect(userArg?.argValue).toBe("userNameBase"); expect(profInfo.loadSecureArg(userArg as IProfArgAttrs)).toBe("userNameBase"); const passwordArg = mergedArgs.knownArgs.find((arg) => arg.argName === "password"); - expect(passwordArg.argValue).toBe("passwordBase"); + expect(passwordArg?.argValue).toBe("passwordBase"); expect(profInfo.loadSecureArg(passwordArg as IProfArgAttrs)).toBe("passwordBase"); }); @@ -1354,10 +1419,10 @@ describe("TeamConfig ProfileInfo tests", () => { const mergedArgs = profInfo.mergeArgsForProfile(profAttrs, { getSecureVals: true }); const userArg = mergedArgs.knownArgs.find((arg) => arg.argName === "user"); - expect(userArg.argValue).toBe("userNameBase"); + expect(userArg?.argValue).toBe("userNameBase"); const passwordArg = mergedArgs.knownArgs.find((arg) => arg.argName === "password"); - expect(passwordArg.argValue).toBe("passwordBase"); + expect(passwordArg?.argValue).toBe("passwordBase"); }); it("should treat secure arg as plain text if loaded from environment variable", async () => { @@ -1384,7 +1449,7 @@ describe("TeamConfig ProfileInfo tests", () => { profInfo.loadSecureArg({ argName: "test", dataType: "string", - argValue: undefined, + argValue: undefined as any, argLoc: { locType: ProfLocType.DEFAULT } }); } catch (error) { @@ -1411,8 +1476,12 @@ describe("TeamConfig ProfileInfo tests", () => { const profAttrs = profInfo.getDefaultProfile("zosmf") as IProfAttrs; const osLocInfo = profInfo.getOsLocInfo(profAttrs); const expectedObjs = [ - { name: profAttrs.profName, path: profAttrs.profLoc.osLoc[0], user: false, global: false }, - { name: profAttrs.profName, path: profAttrs.profLoc.osLoc[0], user: false, global: true } + { name: profAttrs.profName, path: profAttrs.profLoc.osLoc?.[0], user: false, global: false }, + // TODO(zFernand0): Investigate why only the team project is present in the osLoc array + // Possible reason: global layer not loaded by getAllProfiles() + // ---- + // Reseting the loaded configuration in `getZoweDir` may be the root cause. + { name: profAttrs.profName, path: profAttrs.profLoc.osLoc?.[0], user: false, global: true } ]; expect(osLocInfo).toBeDefined(); expect(osLocInfo.length).toBe(expectedObjs.length); @@ -1464,58 +1533,6 @@ describe("TeamConfig ProfileInfo tests", () => { }; // begin schema management tests - describe("readExtendersJsonFromDisk", () => { - // case 1: the JSON file doesn't exist at time of read - it("writes an empty extenders.json file if it doesn't exist on disk", async () => { - const profInfo = createNewProfInfo(teamProjDir); - (profInfo as any).mExtendersJson = { profileTypes: {} }; - jest.spyOn(fs, "existsSync").mockReturnValueOnce(false); - ProfileInfo.readExtendersJsonFromDisk(); - expect(writeFileSyncMock).toHaveBeenCalled(); - }); - - // case 2: JSON file exists on-disk at time of read - it("reads extenders.json from disk if it exists", async () => { - const readFileSyncMock = jest.spyOn(jsonfile, "readFileSync").mockReturnValueOnce({ profileTypes: { - "test": { - from: ["Zowe Client App"] - } - } }); - const profInfo = createNewProfInfo(teamProjDir); - jest.spyOn(fs, "existsSync").mockReturnValueOnce(true); - (profInfo as any).mExtendersJson = ProfileInfo.readExtendersJsonFromDisk(); - expect(readFileSyncMock).toHaveBeenCalled(); - expect((profInfo as any).mExtendersJson).toEqual({ - profileTypes: { - "test": { - from: ["Zowe Client App"] - } - } - }); - }); - }); - - describe("writeExtendersJson", () => { - // case 1: Write operation is successful - it("returns true if written to disk successfully", async () => { - const profInfo = createNewProfInfo(teamProjDir); - (profInfo as any).mExtendersJson = { profileTypes: {} }; - await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - expect(ProfileInfo.writeExtendersJson((profInfo as any).mExtendersJson)).toBe(true); - expect(writeFileSyncMock).toHaveBeenCalled(); - }); - - // case 2: Write operation is unsuccessful - it("returns false if it couldn't write to disk", async () => { - const profInfo = createNewProfInfo(teamProjDir); - (profInfo as any).mExtendersJson = { profileTypes: {} }; - await profInfo.readProfilesFromDisk({ homeDir: teamHomeProjDir }); - writeFileSyncMock.mockImplementation(() => { throw new Error(); }); - expect(ProfileInfo.writeExtendersJson((profInfo as any).mExtendersJson)).toBe(false); - expect(writeFileSyncMock).toHaveBeenCalled(); - }); - }); - describe("updateSchemaAtLayer", () => { const getBlockMocks = () => { return { @@ -1667,7 +1684,7 @@ describe("TeamConfig ProfileInfo tests", () => { } as any); const updateSchemaAtLayerMock = jest.spyOn((ProfileInfo as any).prototype, "updateSchemaAtLayer") .mockReturnValue(expected.res.success); - const writeExtendersJsonMock = jest.spyOn(ProfileInfo, "writeExtendersJson").mockImplementation(); + const writeExtendersJsonMock = jest.spyOn(ConfigUtils, "writeExtendersJson").mockImplementation(); const res = profInfo.addProfileTypeToSchema("some-type", { ...testCase, sourceApp: "Zowe Client App" }); if (expected.res.success) { expect(updateSchemaAtLayerMock).toHaveBeenCalled(); @@ -1715,8 +1732,10 @@ describe("TeamConfig ProfileInfo tests", () => { } } }, - res: { success: false, info: "Both the old and new schemas are unversioned for some-type, but the schemas are different. " - .concat("The new schema was not written to disk, but will still be accessible in-memory.") } + res: { + success: false, info: "Both the old and new schemas are unversioned for some-type, but the schemas are different. " + .concat("The new schema was not written to disk, but will still be accessible in-memory.") + } } ); }); diff --git a/packages/imperative/src/config/__tests__/__resources__/ProfInfoApp_team_config_proj/ProfInfoApp.config.json b/packages/imperative/src/config/__tests__/__resources__/ProfInfoApp_team_config_proj/ProfInfoApp.config.json index 0823095788..669c188f06 100644 --- a/packages/imperative/src/config/__tests__/__resources__/ProfInfoApp_team_config_proj/ProfInfoApp.config.json +++ b/packages/imperative/src/config/__tests__/__resources__/ProfInfoApp_team_config_proj/ProfInfoApp.config.json @@ -72,6 +72,19 @@ }, "typeless": { "properties": {} + }, + "LPAR007": { + "type": "zosmf", + "properties": {}, + "secure": [ + "string", + "boolean", + "number", + "missing-after-this", + "host", + "port", + "rejectUnauthorized" + ] } }, "defaults": { diff --git a/packages/imperative/src/config/__tests__/__resources__/project.config.json b/packages/imperative/src/config/__tests__/__resources__/project.config.json index c2a1b3be7f..5a1f5b485f 100644 --- a/packages/imperative/src/config/__tests__/__resources__/project.config.json +++ b/packages/imperative/src/config/__tests__/__resources__/project.config.json @@ -43,4 +43,4 @@ }, "plugins": [], "autoStore": true -} +} \ No newline at end of file diff --git a/packages/imperative/src/config/index.ts b/packages/imperative/src/config/index.ts index 0a02bfc2b3..60e5d41778 100644 --- a/packages/imperative/src/config/index.ts +++ b/packages/imperative/src/config/index.ts @@ -10,24 +10,25 @@ */ export * from "./src/Config"; -export * from "./src/ConfigAutoStore"; +// export * from "./src/ConfigAutoStore"; +export * from "./src/ConfigBuilder"; export * from "./src/ConfigConstants"; export * from "./src/ConfigSchema"; -export * from "./src/ConfigBuilder"; export * from "./src/ConfigUtils"; +export * from "./src/ConvertV1Profiles"; export * from "./src/ProfileCredentials"; export * from "./src/ProfileInfo"; export * from "./src/ProfInfoErr"; export * from "./src/doc/IConfig"; export * from "./src/doc/IConfigAutoStoreOpts"; export * from "./src/doc/IConfigBuilderOpts"; -export * from "./src/doc/IConfigConvertResult"; export * from "./src/doc/IConfigLayer"; export * from "./src/doc/IConfigOpts"; export * from "./src/doc/IConfigProfile"; export * from "./src/doc/IConfigSchema"; export * from "./src/doc/IConfigSecure"; export * from "./src/doc/IConfigVault"; +export * from "./src/doc/IConvertV1Profiles"; export * from "./src/doc/IProfArgAttrs"; export * from "./src/doc/IProfAttrs"; export * from "./src/doc/IProfInfoUpdatePropOpts"; diff --git a/packages/imperative/src/config/src/Config.ts b/packages/imperative/src/config/src/Config.ts index 7f9a211590..999f568960 100644 --- a/packages/imperative/src/config/src/Config.ts +++ b/packages/imperative/src/config/src/Config.ts @@ -225,7 +225,7 @@ export class Config { try { for (const currLayer of this.mLayers) { - if (allLayers || (currLayer.user === this.mActive.user && currLayer.global === this.mActive.global)) { + if (allLayers || currLayer.user === this.mActive.user && currLayer.global === this.mActive.global) { this.api.layers.write(currLayer); } } @@ -243,7 +243,7 @@ export class Config { * Get absolute file path for a config layer. * For project config files, We search up from our current directory and * ignore the Zowe hone directory (in case our current directory is under - * Zowe home.). For golbal config files we only retrieve config files + * Zowe home.). For global config files we only retrieve config files * from the Zowe home directory. * * @internal @@ -308,7 +308,8 @@ export class Config { * Returns a clone to prevent accidental edits of the original object. */ public get layers(): IConfigLayer[] { - return JSONC.parse(JSONC.stringify(this.mLayers, null, ConfigConstants.INDENT)); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + return JSONC.parse(JSONC.stringify(this.mLayers, null, ConfigConstants.INDENT)) as any; } // _______________________________________________________________________ @@ -502,11 +503,12 @@ export class Config { */ public setSchema(schema: string | object) { const layer = this.layerActive(); - const schemaUri = (typeof schema === "string") ? schema : `./${this.schemaName}`; - const schemaObj = (typeof schema !== "string") ? schema : null; + const schemaUri = typeof schema === "string" ? schema : `./${this.schemaName}`; + const schemaObj = typeof schema !== "string" ? schema : null; if (layer.properties.$schema == null) { - layer.properties = JSONC.parse(JSONC.stringify({ $schema: schemaUri, ...layer.properties }, null, ConfigConstants.INDENT)); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + layer.properties = JSONC.parse(JSONC.stringify({ $schema: schemaUri, ...layer.properties }, null, ConfigConstants.INDENT)) as any; } const schemaInfo = this.getSchemaInfo(); @@ -583,7 +585,8 @@ export class Config { public layerProfiles(layer: IConfigLayer, opts: IConfigMergeOpts = {}): { [key: string]: IConfigProfile } { let properties = layer.properties; if (opts.cloneLayers !== false || opts.maskSecure) { - properties = JSONC.parse(JSONC.stringify(properties, null, ConfigConstants.INDENT)); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + properties = JSONC.parse(JSONC.stringify(properties, null, ConfigConstants.INDENT)) as any; } if (opts.maskSecure) { for (const secureProp of this.api.secure.secureFields(layer)) { @@ -606,7 +609,7 @@ export class Config { * @returns The desired layer object. Null if no layer matches. */ public findLayer(user: boolean, global: boolean): IConfigLayer { - for (const layer of (this.mLayers || [])) { + for (const layer of this.mLayers || []) { if (layer.user === user && layer.global === global) return layer; } @@ -616,8 +619,6 @@ export class Config { /** * Obtain the layer object that is currently active. * - * @internal - * * @returns The active layer object */ public layerActive(): IConfigLayer { diff --git a/packages/imperative/src/config/src/ConfigAutoStore.ts b/packages/imperative/src/config/src/ConfigAutoStore.ts index 069415025d..a399be85ee 100644 --- a/packages/imperative/src/config/src/ConfigAutoStore.ts +++ b/packages/imperative/src/config/src/ConfigAutoStore.ts @@ -46,8 +46,8 @@ export class ConfigAutoStore { */ private static _findActiveProfile(opts: IConfigAutoStoreFindActiveProfileOpts): [string, string] | undefined { const profileTypes = typeof opts.params !== "undefined" ? [ - ...(opts.params.definition.profile?.required || []), - ...(opts.params.definition.profile?.optional || []) + ...opts.params.definition.profile?.required || [], + ...opts.params.definition.profile?.optional || [] ] : opts.profileTypes || []; for (const profType of profileTypes) { @@ -175,9 +175,9 @@ export class ConfigAutoStore { (3) Property is tokenValue and tokenType is missing from service profile, but present in base profile (4) Given profile is just a base profile :yum: */ - if ((!config.api.profiles.exists(profileName) && config.api.profiles.exists(baseProfileName)) || - (profileObj[propName] == null && !profileSecureProps.includes(propName) && - (baseProfileObj[propName] != null || baseProfileSecureProps.includes(propName))) || + if (!config.api.profiles.exists(profileName) && config.api.profiles.exists(baseProfileName) || + profileObj[propName] == null && !profileSecureProps.includes(propName) && + (baseProfileObj[propName] != null || baseProfileSecureProps.includes(propName)) || (propName === "tokenValue" && profileObj.tokenType == null && baseProfileObj.tokenType != null || profileType === "base") ) { diff --git a/packages/imperative/src/config/src/ConfigBuilder.ts b/packages/imperative/src/config/src/ConfigBuilder.ts index ea94052006..f72bd34eab 100644 --- a/packages/imperative/src/config/src/ConfigBuilder.ts +++ b/packages/imperative/src/config/src/ConfigBuilder.ts @@ -9,51 +9,53 @@ * */ -import * as path from "path"; import * as lodash from "lodash"; -import { ProfileIO, ProfilesConstants, ProfileUtils } from "../../profiles"; import { IImperativeConfig } from "../../imperative"; import { Config } from "./Config"; import { IConfig } from "./doc/IConfig"; import { IConfigBuilderOpts } from "./doc/IConfigBuilderOpts"; -import { CredentialManagerFactory } from "../../security"; -import { IConfigConvertResult } from "./doc/IConfigConvertResult"; import { ICommandProfileTypeConfiguration } from "../../cmd"; +import { ConfigUtils } from "./ConfigUtils"; export class ConfigBuilder { /** * Build a new Config object from an Imperative CLI app configuration. * @param impConfig The Imperative CLI app configuration. + * @param globalConfig Is the config to be a global config? * @param opts Options to control aspects of the builder. */ - public static async build(impConfig: IImperativeConfig, opts?: IConfigBuilderOpts): Promise { + public static async build(impConfig: IImperativeConfig, globalConfig: boolean, opts?: IConfigBuilderOpts): Promise { opts = opts || {}; - const config: IConfig = Config.empty(); + const builtConfig: IConfig = Config.empty(); for (const profile of impConfig.profiles) { const defaultProfile = ConfigBuilder.buildDefaultProfile(profile, opts); + // Name our profile differently in a global config vs a project config + const profileName: string = ConfigUtils.formGlobOrProjProfileNm(profile.type, globalConfig); + // Add the profile to config and set it as default - lodash.set(config, `profiles.${profile.type}`, defaultProfile); + lodash.set(builtConfig, `profiles.${profileName}`, defaultProfile); if (opts.populateProperties) { - config.defaults[profile.type] = profile.type; + builtConfig.defaults[profile.type] = profileName; } } // Prompt for properties missing from base profile if (impConfig.baseProfile != null && opts.getValueBack != null) { + const baseProfileNm: string = ConfigUtils.formGlobOrProjProfileNm(impConfig.baseProfile.type, globalConfig); for (const [k, v] of Object.entries(impConfig.baseProfile.schema.properties)) { if (v.includeInTemplate && v.optionDefinition?.defaultValue == null) { const propValue = await opts.getValueBack(k, v); if (propValue != null) { - lodash.set(config, `profiles.${impConfig.baseProfile.type}.properties.${k}`, propValue); + lodash.set(builtConfig, `profiles.${baseProfileNm}.properties.${k}`, propValue); } } } } - return { ...config, autoStore: true }; + return { ...builtConfig, autoStore: true }; } public static buildDefaultProfile(profile: ICommandProfileTypeConfiguration, opts?: IConfigBuilderOpts): { @@ -87,135 +89,6 @@ export class ConfigBuilder { }; } - /** - * Convert existing v1 profiles to a Config object and report any conversion failures. - * @param profilesRootDir Root directory where v1 profiles are stored. - * @returns Results object including new config and error details for profiles that failed to convert. - */ - public static async convert(profilesRootDir: string): Promise { - const result: IConfigConvertResult = { - config: Config.empty(), - profilesConverted: {}, - profilesFailed: [] - }; - - for (const profileType of ProfileIO.getAllProfileDirectories(profilesRootDir)) { - const profileTypeDir = path.join(profilesRootDir, profileType); - const profileNames = ProfileIO.getAllProfileNames(profileTypeDir, ".yaml", `${profileType}_meta`); - if (profileNames.length === 0) { - continue; - } - - for (const profileName of profileNames) { - try { - const profileFilePath = path.join(profileTypeDir, `${profileName}.yaml`); - const profileProps = ProfileIO.readProfileFile(profileFilePath, profileType); - const secureProps = []; - - for (const [key, value] of Object.entries(profileProps)) { - if (value.toString().startsWith(ProfilesConstants.PROFILES_OPTION_SECURELY_STORED)) { - const secureValue = await CredentialManagerFactory.manager.load( - ProfileUtils.getProfilePropertyKey(profileType, profileName, key), true); - if (secureValue != null) { - profileProps[key] = JSON.parse(secureValue); - secureProps.push(key); - } else { - delete profileProps[key]; - } - } - } - - result.config.profiles[ProfileUtils.getProfileMapKey(profileType, profileName)] = { - type: profileType, - properties: profileProps, - secure: secureProps - }; - - result.profilesConverted[profileType] = [...(result.profilesConverted[profileType] || []), profileName]; - } catch (error) { - result.profilesFailed.push({ name: profileName, type: profileType, error }); - } - } - - try { - const metaFilePath = path.join(profileTypeDir, `${profileType}_meta.yaml`); - const profileMetaFile = ProfileIO.readMetaFile(metaFilePath); - if (profileMetaFile.defaultProfile != null) { - result.config.defaults[profileType] = ProfileUtils.getProfileMapKey(profileType, profileMetaFile.defaultProfile); - } - } catch (error) { - result.profilesFailed.push({ type: profileType, error }); - } - } - - // convert profile property names that have been changed for V2 - ConfigBuilder.convertPropNames(result); - result.config.autoStore = true; - return result; - } - - /** - * Convert a set of known property names that have been renamed for - * V2 conformance to their new names. - * - * @param conversionResult The conversion result structure in which we shall - * rename obsolete property names to their V2-compliant names. - */ - private static convertPropNames(conversionResult: IConfigConvertResult): void { - const nameConversions = [ - ["hostname", "host"], - ["username", "user"], - ["pass", "password"] - ]; - - // interate through all of the recorded profiles - for (const currProfNm of Object.keys(conversionResult.config.profiles)) { - // iterate through the non-secure properties of the current profile - const profPropsToConvert = []; - const currProps = conversionResult.config.profiles[currProfNm].properties; - for (const [currPropName, currPropVal] of Object.entries(currProps)) { - // iterate through the set of names that we must convert - for (const [oldPropName, newPropName] of nameConversions) { - if (currPropName === oldPropName) { - /* Store the property conversion info for later replacement. - * We do not want to add and delete properties while - * we are iterating the properties. - */ - const propToConvert = [oldPropName, newPropName, currPropVal]; - profPropsToConvert.push(propToConvert); - - /* We recorded the replacement for this property name. - * No need to look for more name conversions on this name. - */ - break; - } - } - } // end for all properties - - // convert the non-secure property names for the current profile - for (const [oldPropName, newPropName, propValue] of profPropsToConvert) { - delete currProps[oldPropName]; - currProps[newPropName] = propValue; - } - - // iterate through the secure property names of the current profile - const currSecProps = conversionResult.config.profiles[currProfNm].secure; - for (let secInx = 0; secInx < currSecProps.length; secInx++) { - // iterate through the set of names that we must convert - for (const [oldPropName, newPropName] of nameConversions) { - if (currSecProps[secInx] === oldPropName) { - currSecProps[secInx] = newPropName; - - /* We replaced this secure property name. - * No need to look for more name conversions on this name. - */ - break; - } - } - } - } // end for all profiles - } // end convertPropNames - /** * Returns empty value that is appropriate for the property type. * @param propType The type of profile property @@ -227,12 +100,12 @@ export class ConfigBuilder { propType = propType[0]; } switch (propType) { - case "string": return ""; - case "number": return 0; - case "object": return {}; - case "array": return []; + case "string": return ""; + case "number": return 0; + case "object": return {}; + case "array": return []; case "boolean": return false; - default: return null; + default: return null; } } } diff --git a/packages/imperative/src/config/src/ConfigSchema.ts b/packages/imperative/src/config/src/ConfigSchema.ts index 17a8cd77cb..f0471c12fa 100644 --- a/packages/imperative/src/config/src/ConfigSchema.ts +++ b/packages/imperative/src/config/src/ConfigSchema.ts @@ -388,7 +388,7 @@ export class ConfigSchema { */ public static updateSchema(options?: IConfigUpdateSchemaOptions): IConfigUpdateSchemaPaths { // Handle default values - const opts: IConfigUpdateSchemaOptions = { layer: "active", depth: 0, ...(options ?? {}) }; + const opts: IConfigUpdateSchemaOptions = { layer: "active", depth: 0, ...options ?? {} }; // Build schema from loaded config if needed opts.schema = opts.schema ?? ConfigSchema.buildSchema(ImperativeConfig.instance.loadedConfig.profiles); diff --git a/packages/imperative/src/config/src/ConfigUtils.ts b/packages/imperative/src/config/src/ConfigUtils.ts index 6a1540fe7a..79b8640537 100644 --- a/packages/imperative/src/config/src/ConfigUtils.ts +++ b/packages/imperative/src/config/src/ConfigUtils.ts @@ -9,14 +9,78 @@ * */ -import { CredentialManagerFactory } from "../../security"; +import { homedir as osHomedir } from "os"; +import { normalize as pathNormalize, join as pathJoin } from "path"; +import { existsSync as fsExistsSync } from "fs"; +import * as jsonfile from "jsonfile"; + +import { CredentialManagerFactory } from "../../security/src/CredentialManagerFactory"; import { ICommandArguments } from "../../cmd"; import { ImperativeConfig } from "../../utilities"; import { ImperativeError } from "../../error"; +import { LoggerManager } from "../../logger/src/LoggerManager"; +import { LoggingConfigurer } from "../../imperative/src/LoggingConfigurer"; +import { Logger } from "../../logger/src/Logger"; +import { EnvironmentalVariableSettings } from "../../imperative/src/env/EnvironmentalVariableSettings"; +import { IConfigProfile } from "./doc/IConfigProfile"; +import { IExtendersJsonOpts } from "./doc/IExtenderOpts"; export class ConfigUtils { /** - * Coeerces string property value to a boolean or number type. + * Retrieves the Zowe CLI home directory. In the situation Imperative has + * not initialized it we use a default value. + * @returns {string} - Returns the Zowe home directory + */ + public static getZoweDir(): string { + const defaultHome = pathJoin(osHomedir(), ".zowe"); + if (ImperativeConfig.instance.loadedConfig?.defaultHome !== defaultHome) { + ImperativeConfig.instance.loadedConfig = { + name: "zowe", + defaultHome, + envVariablePrefix: "ZOWE" + }; + } + return ImperativeConfig.instance.cliHome; + } + + /** + * Reads the `extenders.json` file from the CLI home directory. + * Called once in `readProfilesFromDisk` and cached to minimize I/O operations. + * @internal + * @throws If the extenders.json file cannot be created when it does not exist. + * @throws If the extenders.json file cannot be read. + */ + public static readExtendersJson(): IExtendersJsonOpts { + const cliHome = ImperativeConfig.instance.loadedConfig != null ? ImperativeConfig.instance.cliHome : ConfigUtils.getZoweDir(); + const extenderJsonPath = pathJoin(cliHome, "extenders.json"); + if (!fsExistsSync(extenderJsonPath)) { + jsonfile.writeFileSync(extenderJsonPath, { + profileTypes: {} + }, { spaces: 4 }); + return { profileTypes: {} }; + } else { + return jsonfile.readFileSync(extenderJsonPath); + } + } + + /** + * Attempts to write to the `extenders.json` file in the CLI home directory. + * @returns `true` if written successfully; `false` otherwise + * @internal + */ + public static writeExtendersJson(obj: IExtendersJsonOpts): boolean { + try { + const extenderJsonPath = pathJoin(ConfigUtils.getZoweDir(), "extenders.json"); + jsonfile.writeFileSync(extenderJsonPath, obj, { spaces: 4 }); + } catch (err) { + return false; + } + + return true; + } + + /** + * Coerces string property value to a boolean or number type. * @param value String value * @param type Property type defined in the schema * @returns Boolean, number, or string @@ -65,6 +129,37 @@ export class ConfigUtils { return fullPath === partialPath || fullPath.startsWith(partialPath + ".profiles."); } + /** + * Returns an indicator that the user has no team configuration, but we + * detected the existence of old-school V1 profiles. We will not work with the + * V1 profiles. This function can let you tell a user that they are incorrectly + * trying to use V1 profiles. + * + * @returns True - Means there is *NO* team config *AND* we detected that a V1 profile exists. + * False otherwise. + */ + public static get onlyV1ProfilesExist(): boolean { + if (ImperativeConfig.instance.config?.exists) { + // we have a team config + return false; + } + + let v1ZosmfProfileFileNm: string; + try { + v1ZosmfProfileFileNm = pathNormalize(ImperativeConfig.instance.cliHome + "/profiles/zosmf/zosmf_meta.yaml"); + } catch (_thrownErr) { + // We failed to get the CLI home directory. So, we definitely have no V1 profiles. + return false; + } + + if (fsExistsSync(v1ZosmfProfileFileNm)) { + // we found V1 profiles + return true; + } + + return false; + } + /** * Form an error message for failures to securely save a value. * @param solution Text that our caller can supply for a solution. @@ -73,11 +168,131 @@ export class ConfigUtils { public static secureSaveError(solution?: string): ImperativeError { let details = CredentialManagerFactory.manager.secureErrorDetails(); if (solution != null) { - details = (details != null) ? (details + `\n - ${solution}`) : solution; + details = details != null ? details + `\n - ${solution}` : solution; } return new ImperativeError({ msg: "Unable to securely save credentials.", additionalDetails: details }); } + + // _______________________________________________________________________ + /** + * Perform a rudimentary initialization of some Imperative utilities. + * We must do this because VSCode apps do not typically call imperative.init. + * @internal + */ + public static initImpUtils(appName: string) { + // create a rudimentary ImperativeConfig if it has not been initialized + if (ImperativeConfig.instance.loadedConfig == null) { + let homeDir: string = null; + const envVarPrefix = appName.toUpperCase(); + const envVarNm = envVarPrefix + EnvironmentalVariableSettings.CLI_HOME_SUFFIX; + if (process.env[envVarNm] === undefined) { + // use OS home directory + homeDir = pathJoin(osHomedir(), "." + appName.toLowerCase()); + } else { + // use the available environment variable + homeDir = pathNormalize(process.env[envVarNm]); + } + ImperativeConfig.instance.loadedConfig = { + name: appName, + defaultHome: homeDir, + envVariablePrefix: envVarPrefix + }; + ImperativeConfig.instance.rootCommandName = appName; + } + + // initialize logging + if (LoggerManager.instance.isLoggerInit === false) { + const loggingConfig = LoggingConfigurer.configureLogger( + ImperativeConfig.instance.cliHome, ImperativeConfig.instance.loadedConfig + ); + Logger.initLogger(loggingConfig); + } + return Logger.getImperativeLogger(); + } + + // _______________________________________________________________________ + /** + * Form a profile name of a given profile type to be used as a default + * profile name. The name can vary based on whether the configuration to + * contain the profile is a global config or a project config. + * + * Currently, we only form a different global/project profile name for + * a base profile. The profile name for any other profile type is currently + * set to the profile type string. + * + * @param profileType + * The profile type for which we will form a name. + * + * @param globalConfig + * Indicator that the caller knows that the profile name will be + * for a globalConfig (true) or project config (false). + * If globalConfig is not supplied, we interrogate any existing + * Config object to determine whether to form a global or project + * profile name. + * + * @returns + * A string to be used as the profile name for the specified profile type. + */ + public static formGlobOrProjProfileNm(profileType: string, globalConfig: boolean = null): string { + if (profileType !== "base") { + // everything except base profiles use profile type as the profile name + return profileType; + } + + // were we told that this is for a global or project config? + if (globalConfig === true) { + return `global_${profileType}`; + + } else if (globalConfig === false) { + return `project_${profileType}`; + + } else { + // determine from existing config whether the profile is intended for a project config + const existingConfig = ImperativeConfig.instance.config; + for (const nextLayer of existingConfig.layers) { + // if desired profile type exists in the project layer, it wins + if (nextLayer.global === false) { + if (ConfigUtils.findProfTypeInNestedProfiles(profileType, existingConfig.layerProfiles(nextLayer))) { + return `project_${profileType}`; + } + } + } + } + // since we did not find the profile type at the project layers, return a global name + return `global_${profileType}`; + } + + // _______________________________________________________________________ + /** + * Find the specified profile type in the specified (or nested) profiles. + * + * @param profileType + * The profile type to search for. + * + * @param profilesObj + * The profile object in which we should search. + * + * @returns + * True if we find the profile type. False otherwise. + */ + private static findProfTypeInNestedProfiles( + profileType: string, + profilesObj: { [key: string]: IConfigProfile } + ): boolean { + for (const nextProfileObj of Object.values(profilesObj)) { + if (nextProfileObj?.type === profileType) { + return true; + } + // The specified type was not in nextProfileObj. Recursively look in its nested profiles. + if (nextProfileObj?.profiles) { + if (ConfigUtils.findProfTypeInNestedProfiles(profileType, nextProfileObj.profiles)) { + return true; + } + } + } + return false; + } } diff --git a/packages/imperative/src/config/src/ConvertV1Profiles.ts b/packages/imperative/src/config/src/ConvertV1Profiles.ts new file mode 100644 index 0000000000..4669d2f8dd --- /dev/null +++ b/packages/imperative/src/config/src/ConvertV1Profiles.ts @@ -0,0 +1,759 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import * as fs from "fs"; +import * as path from "path"; +import { readFileSync } from "jsonfile"; +import { removeSync } from "fs-extra"; +import stripAnsi = require("strip-ansi"); +import { V1ProfileRead, ProfilesConstants, ProfileUtils } from "../../profiles"; +import { Config } from "./Config"; +import { IConfig } from "./doc/IConfig"; +import { CredentialManagerFactory } from "../../security"; +import { IConvertV1ProfOpts, ConvertMsg, ConvertMsgFmt, IConvertV1ProfResult } from "./doc/IConvertV1Profiles"; +import { IImperativeOverrides } from "../../imperative/src/doc/IImperativeOverrides"; +import { keyring } from "@zowe/secrets-for-zowe-sdk"; +import { AppSettings } from "../../settings"; +import { ISettingsFile } from "../../settings/src/doc/ISettingsFile"; +import { ImperativeConfig } from "../../utilities"; +import { CredentialManagerOverride } from "../../security/src/CredentialManagerOverride"; +import { OverridesLoader } from "../../imperative/src/OverridesLoader"; +import { ConfigSchema } from "./ConfigSchema"; +import { ProfileInfo } from "./ProfileInfo"; +import { Logger } from "../../logger"; + +interface IOldPluginInfo { + /** + * List of CLI plug-ins to uninstall + */ + plugins: string[]; + /** + * List of overrides to remove from app settings + */ + overrides: (keyof IImperativeOverrides)[]; +} + +export class ConvertV1Profiles { + private static readonly noCfgFilePathNm: string = "CouldNotGetPathToConfigFile"; + private static readonly credMgrKey: string = "CredentialManager"; + private static readonly oldScsPluginNm = "@zowe/secure-credential-store-for-zowe-cli"; + private static readonly builtInCredMgrNm: string = "@zowe/cli"; + + private static profileInfo: ProfileInfo = null; + private static oldScsPluginWasConfigured: boolean = false; + private static convertOpts: IConvertV1ProfOpts = null; + private static convertResult: IConvertV1ProfResult = null; + private static profilesRootDir: string = "NotYetSet"; + private static oldProfilesDir: string = "NotYetSet"; + private static zoweKeyRing: typeof keyring = undefined; + + /** + * Convert V1 profiles into a zowe.config.json file. + * + * It will also do the following: + * Create a zowe.schema.json file. + * Migrate V1 secure properties into the current consolidated Zowe client secure properties. + * Replace old SCS-plugin credential manager override with the Zowe embedded SCS. + * Delete old V1 profiles (and old V1 secure properties) if requested. + * + * Calling this function after having already converted, will not attempt to + * convert again. However it will still delete the old profiles if requested. + * + * You should **NOT** initialize the secure credential manager before calling this function. + * The CredMgr can only be initialized once. If the old V1 SCS-plugin happens to be configured + * as the CredMgr when this function is called, the old V1 SCS-plugin CredMgr is unable + * to create the current consolidated Zowe client secure properties. Users will have to + * re-enter all of their credentials. + * + * @param convertOpts Options that will control the conversion process. + * @returns Result object into which messages and stats are stored. + */ + public static async convert(convertOpts: IConvertV1ProfOpts): Promise { + ConvertV1Profiles.profileInfo = convertOpts.profileInfo; + + // initialize our result, which will be used by our utility functions, and returned by us + ConvertV1Profiles.convertResult = { + msgs: [], + v1ScsPluginName: null, + credsWereMigrated: true, + cfgFilePathNm: ConvertV1Profiles.noCfgFilePathNm, + numProfilesFound: 0, + profilesConverted: {}, + profilesFailed: [] + }; + + // record our conversion options so that our utility functions can access them + ConvertV1Profiles.convertOpts = convertOpts; + + try { + ConvertV1Profiles.profilesRootDir = ProfileUtils.constructProfilesRootDirectory(ImperativeConfig.instance.cliHome); + ConvertV1Profiles.oldProfilesDir = `${ConvertV1Profiles.profilesRootDir.replace(/[\\/]$/, "")}-old`; + + if (await ConvertV1Profiles.isConversionNeeded()) { + ConvertV1Profiles.replaceOldCredMgrOverride(); + await ConvertV1Profiles.initCredMgr(); + await ConvertV1Profiles.moveV1ProfilesToConfigFile(); + } + + if (convertOpts.deleteV1Profs) { + await ConvertV1Profiles.deleteV1Profiles(); + } + + // Report if the old SCS plugin should be uninstalled + if (ConvertV1Profiles.convertResult.v1ScsPluginName != null) { + let verb = "will"; + if (ConvertV1Profiles.profileInfo) { + verb = "should"; + } + let uninstallMsg: string = `The obsolete plug-in ${ConvertV1Profiles.convertResult.v1ScsPluginName} ` + + `${verb} be uninstalled because the SCS is now embedded within the Zowe clients.`; + + if (ConvertV1Profiles.profileInfo) { + uninstallMsg += ` Zowe CLI plugins can only be uninstalled by the CLI. Use the command ` + + `'zowe plugins uninstall ${ConvertV1Profiles.convertResult.v1ScsPluginName}'.`; + } + ConvertV1Profiles.addToConvertMsgs(ConvertMsgFmt.REPORT_LINE | ConvertMsgFmt.PARAGRAPH, uninstallMsg); + } + } catch (error) { + ConvertV1Profiles.addExceptionToConvertMsgs("Encountered the following error while trying to convert V1 profiles:", error); + } + + return ConvertV1Profiles.convertResult; + } + + /** + * Detect whether we must convert any V1 profiles to a zowe client configuration. + * @returns True means we must do a conversion. False otherwise. + */ + private static async isConversionNeeded(): Promise { + ConvertV1Profiles.convertResult.numProfilesFound = 0; + + if (ImperativeConfig.instance.config == null) { + // Initialization for VSCode extensions does not create the config property, so create it now. + ImperativeConfig.instance.config = await Config.load( + ImperativeConfig.instance.loadedConfig.name, + { + homeDir: ImperativeConfig.instance.loadedConfig.defaultHome + } + ); + } + + if (ImperativeConfig.instance.config?.exists) { + // We do not convert if we already have an existing zowe client config + ConvertV1Profiles.putCfgFileNmInResult(ImperativeConfig.instance.config); + ConvertV1Profiles.addToConvertMsgs( + ConvertMsgFmt.REPORT_LINE, + `Did not convert any V1 profiles because a current Zowe client configuration ` + + `was found at ${ConvertV1Profiles.convertResult.cfgFilePathNm}.` + ); + } else { + // with no client config, the existence of old V1 profiles dictates if we will convert + const noProfilesMsg = `Did not convert any V1 profiles because no V1 profiles were found at ` + + `${ConvertV1Profiles.profilesRootDir}.`; + try { + ConvertV1Profiles.convertResult.numProfilesFound = + ConvertV1Profiles.getOldProfileCount(ConvertV1Profiles.profilesRootDir); + if (ConvertV1Profiles.convertResult.numProfilesFound === 0) { + ConvertV1Profiles.addToConvertMsgs(ConvertMsgFmt.REPORT_LINE, noProfilesMsg); + } + } catch (error) { + // did the profiles directory not exist? + if (error?.additionalDetails?.code === "ENOENT") { + ConvertV1Profiles.addToConvertMsgs(ConvertMsgFmt.REPORT_LINE, noProfilesMsg); + } else { + // must have been some sort of I/O error + ConvertV1Profiles.addExceptionToConvertMsgs( + `Failed to get V1 profiles in ${ConvertV1Profiles.profilesRootDir}.`, error + ); + } + } + } + return ConvertV1Profiles.convertResult.numProfilesFound > 0; + } + + /** + * Replace any detected oldCredMgr override entry in settings.json with the Zowe embedded credMgr. + * + * After the replacement of the credential manager override, we can then initialize + * credential manager later in this class. + */ + private static replaceOldCredMgrOverride(): void { + const oldPluginInfo = ConvertV1Profiles.getOldPluginInfo(); + for (const override of oldPluginInfo.overrides) { + if (override === ConvertV1Profiles.credMgrKey) { + try { + AppSettings.instance.set("overrides", ConvertV1Profiles.credMgrKey, CredentialManagerOverride.DEFAULT_CRED_MGR_NAME); + if (ImperativeConfig.instance.loadedConfig.overrides?.CredentialManager != null) { + delete ImperativeConfig.instance.loadedConfig.overrides.CredentialManager; + } + } catch (error) { + ConvertV1Profiles.convertResult.credsWereMigrated = false; + ConvertV1Profiles.addExceptionToConvertMsgs("Failed to replace credential manager override setting.", error); + } + } + } + + /* We only had one override in V1 - the old SCS plugin. + * So, despite the array for multiple plugins, we just report + * the first plugin name in the array as the plugin that our + * caller should uninstall. + */ + ConvertV1Profiles.convertResult.v1ScsPluginName = + oldPluginInfo.plugins.length > 0 ? oldPluginInfo.plugins[0] : null; + } + + /** + * Initialize credential manager so that we can migrate the secure properties that are + * stored for V1 profiles to new secure properties for the converted config that we will create. + * + * For all CLI commands other than convert-profiles, the credential manager is loaded in + * Imperative.init and frozen with Object.freeze so it cannot be modified later on. + * Because convert-profiles cannot create new secure properties for the converted config + * (if the old SCS plugin credMgr is already loaded), Imperative.init does not load the + * credential manager for the convert-profiles command. + * + * VSCode extensions must also avoid initializing the Credential Manager before calling + * ConvertV1Profiles.convert. + * + * If we encounter an error when trying to initialize the credential manager, we report (through + * ConvertV1Profiles.convertResult.credsWereMigrated) that creds were not migrated. + */ + private static async initCredMgr(): Promise { + if (CredentialManagerFactory.initialized) { + if (ConvertV1Profiles.oldScsPluginWasConfigured) { + Logger.getImperativeLogger().error( + `Credential manager has already been initialized with the old SCS plugin ` + + `${ConvertV1Profiles.oldScsPluginNm}. Old credentials cannot be migrated.` + ); + } + } else { + // we must initialize credMgr to get and store credentials + try { + if (ConvertV1Profiles.profileInfo) { + // Initialize CredMgr using the profileInfo object supplied by a VS Code extension + await ConvertV1Profiles.profileInfo.readProfilesFromDisk(); + } else { + // Initialize CredMgr using CLI techniques. + await OverridesLoader.load(ImperativeConfig.instance.loadedConfig, + ImperativeConfig.instance.callerPackageJson + ); + } + } catch (error) { + ConvertV1Profiles.convertResult.credsWereMigrated = false; + ConvertV1Profiles.addExceptionToConvertMsgs("Failed to initialize CredentialManager", error); + } + } + } + + /** + * Move the contents of existing v1 profiles to a zowe client config file. + * + * @returns The path name to the new zowe client config file (null upon failure). + */ + private static async moveV1ProfilesToConfigFile(): Promise { + const convertedConfig: IConfig = Config.empty(); + + for (const profileType of V1ProfileRead.getAllProfileDirectories(ConvertV1Profiles.profilesRootDir)) { + const profileTypeDir = path.join(ConvertV1Profiles.profilesRootDir, profileType); + const profileNames = V1ProfileRead.getAllProfileNames(profileTypeDir, ".yaml", `${profileType}_meta`); + if (profileNames.length === 0) { + continue; + } + + for (const profileName of profileNames) { + try { + const profileFilePath = path.join(profileTypeDir, `${profileName}.yaml`); + const profileProps = V1ProfileRead.readProfileFile(profileFilePath, profileType); + const secureProps = []; + + for (const [key, value] of Object.entries(profileProps)) { + if (value.toString().startsWith(ProfilesConstants.PROFILES_OPTION_SECURELY_STORED)) { + const secureValue = await CredentialManagerFactory.manager.load( + ProfileUtils.getProfilePropertyKey(profileType, profileName, key), true); + if (secureValue != null) { + profileProps[key] = JSON.parse(secureValue); + secureProps.push(key); + } else { + delete profileProps[key]; + } + } + } + + convertedConfig.profiles[ProfileUtils.getProfileMapKey(profileType, profileName)] = { + type: profileType, + properties: profileProps, + secure: secureProps + }; + + ConvertV1Profiles.convertResult.profilesConverted[profileType] = [ + ...ConvertV1Profiles.convertResult.profilesConverted[profileType] || [], profileName + ]; + } catch (error) { + ConvertV1Profiles.convertResult.credsWereMigrated = false; + ConvertV1Profiles.convertResult.profilesFailed.push({ name: profileName, type: profileType, error }); + ConvertV1Profiles.addExceptionToConvertMsgs( + `Failed to read '${profileType}' profile named '${profileName}'`, error + ); + } + } + + try { + const metaFilePath = path.join(profileTypeDir, `${profileType}_meta.yaml`); + const profileMetaFile = V1ProfileRead.readMetaFile(metaFilePath); + if (profileMetaFile.defaultProfile != null) { + convertedConfig.defaults[profileType] = ProfileUtils.getProfileMapKey(profileType, profileMetaFile.defaultProfile); + } + } catch (error) { + ConvertV1Profiles.convertResult.profilesFailed.push({ type: profileType, error }); + ConvertV1Profiles.addExceptionToConvertMsgs(`Failed to find default '${profileType}' profile.`, error); + } + } + + // convert profile property names that were changed starting in V2 + ConvertV1Profiles.convertPropNames(convertedConfig); + convertedConfig.autoStore = true; + + // report the successfully converted profiles + for (const [k, v] of Object.entries(ConvertV1Profiles.convertResult.profilesConverted)) { + ConvertV1Profiles.addToConvertMsgs( + ConvertMsgFmt.REPORT_LINE, + `Converted ${k} profiles: ${v.join(", ")}` + ); + } + + // report the profiles that we failed to convert + if (ConvertV1Profiles.convertResult.profilesFailed.length > 0) { + ConvertV1Profiles.addToConvertMsgs( + ConvertMsgFmt.ERROR_LINE | ConvertMsgFmt.PARAGRAPH, + `Unable to convert ${ConvertV1Profiles.convertResult.profilesFailed.length} profile(s).` + ); + } + + await ConvertV1Profiles.createNewConfigFile(convertedConfig); + } + + /** + * Create a new zowe client config file from an IConfig object. + * Store the name of the new config file in our convertResult object. + * + * @param convertedConfig IConfig object created as a result of V1 profile conversion. + * @returns string - Path name to the newly created config file. + */ + private static async createNewConfigFile(convertedConfig: IConfig): Promise { + if (typeof ImperativeConfig.instance.config.mVault === "undefined" || + ImperativeConfig.instance.config.mVault === null || + Object.keys(ImperativeConfig.instance.config.mVault).length == 0 + ) { + // Either the vault does not exist or it is empty. So create a vault. + ImperativeConfig.instance.config.mVault = { + load: (key: string): Promise => { + return CredentialManagerFactory.manager.load(key, true); + }, + save: (key: string, value: any): Promise => { + return CredentialManagerFactory.manager.save(key, value); + } + }; + } + + const newConfig = ImperativeConfig.instance.config; + newConfig.api.layers.activate(false, true); + newConfig.api.layers.merge(convertedConfig); + ConvertV1Profiles.loadV1Schemas(); + ConfigSchema.updateSchema(); + await newConfig.save(); + ConvertV1Profiles.putCfgFileNmInResult(newConfig); + + try { + fs.renameSync(ConvertV1Profiles.profilesRootDir, ConvertV1Profiles.oldProfilesDir); + + // Only tell the user about moving the V1 profiles if we are NOT going to delete them + if (!ConvertV1Profiles.convertOpts.deleteV1Profs) { + ConvertV1Profiles.addToConvertMsgs( + ConvertMsgFmt.REPORT_LINE | ConvertMsgFmt.PARAGRAPH, + `Your old V1 profiles have been moved to ${ConvertV1Profiles.oldProfilesDir}. ` + + `Delete them by re-running this operation and requesting deletion.` + ); + } + } catch (error) { + ConvertV1Profiles.addExceptionToConvertMsgs( + `Failed to rename profiles directory to ${ConvertV1Profiles.oldProfilesDir}:`, error + ); + } + + ConvertV1Profiles.addToConvertMsgs( + ConvertMsgFmt.REPORT_LINE | ConvertMsgFmt.PARAGRAPH, + `Your new profiles have been saved to ${ConvertV1Profiles.convertResult.cfgFilePathNm}. ` + + `To change your configuration, update that file in your text editor.` + ); + } + + /** + * Load V1 profile schemas, which will not have been loaded for VSCode extensions. + */ + private static loadV1Schemas(): void { + if (!Object.hasOwn(ImperativeConfig.instance.loadedConfig, "profiles")) { + // since no schemas are loaded, we read them from the V1 profiles directory + ImperativeConfig.instance.loadedConfig.profiles = []; + const v1ProfileTypes = fs.existsSync(ConvertV1Profiles.profilesRootDir) ? + V1ProfileRead.getAllProfileDirectories(ConvertV1Profiles.profilesRootDir) : []; + + for (const profType of v1ProfileTypes) { + const schemaFileNm = path.join(ConvertV1Profiles.profilesRootDir, profType, profType + "_meta.yaml"); + if (fs.existsSync(schemaFileNm)) { + try { + const schemaContent = V1ProfileRead.readMetaFile(schemaFileNm); + ImperativeConfig.instance.loadedConfig.profiles.push(schemaContent.configuration); + } catch (error) { + ConvertV1Profiles.addExceptionToConvertMsgs( + `Failed to load schema for profile type ${profType} from file ${schemaFileNm}`, error + ); + } + } + } + } + } + + /** + * Put the path name to the config file, obtained from the supplied Config object, + * into our result object. + * + * @param configForPath The config object from which we will extract the path. + */ + private static putCfgFileNmInResult(configForPath: Config): void { + try { + ConvertV1Profiles.convertResult.cfgFilePathNm = configForPath?.layerActive().path; + } catch (error) { + ConvertV1Profiles.addExceptionToConvertMsgs("Failed to retrieve the path to the config file.", error); + } + if (!ConvertV1Profiles.convertResult.cfgFilePathNm) { + ConvertV1Profiles.convertResult.cfgFilePathNm = ConvertV1Profiles.noCfgFilePathNm; + } + } + + /** + * Delete the V1 profiles that have been converted. + * We also delete the secure credentials stored for those V1 profiles. + */ + private static async deleteV1Profiles(): Promise { + // Delete the profiles directory + try { + if (fs.existsSync(ConvertV1Profiles.oldProfilesDir)) { + removeSync(ConvertV1Profiles.oldProfilesDir); + ConvertV1Profiles.addToConvertMsgs( + ConvertMsgFmt.REPORT_LINE | ConvertMsgFmt.PARAGRAPH, + `Deleted the old profiles directory ${ConvertV1Profiles.oldProfilesDir}.` + ); + } else { + ConvertV1Profiles.addToConvertMsgs( + ConvertMsgFmt.REPORT_LINE | ConvertMsgFmt.PARAGRAPH, + `The old profiles directory ${ConvertV1Profiles.oldProfilesDir} did not exist.` + ); + } + } catch (error) { + ConvertV1Profiles.addExceptionToConvertMsgs( + `Failed to delete the profiles directory ${ConvertV1Profiles.oldProfilesDir}`, error + ); + } + + // Delete the securely stored credentials + if (await ConvertV1Profiles.isZoweKeyRingAvailable()) { + let deleteMsgFormat: any = ConvertMsgFmt.PARAGRAPH; + const knownServices = [ConvertV1Profiles.builtInCredMgrNm, "@brightside/core", "Zowe-Plugin", "Broadcom-Plugin", "Zowe"]; + for (const service of knownServices) { + const accounts = await ConvertV1Profiles.findOldSecureProps(service); + for (const account of accounts) { + if (!account.includes("secure_config_props")) { + const success = await ConvertV1Profiles.deleteOldSecureProps(service, account); + const errMsgTrailer = `obsolete secure value ${service}/${account}`; + if (success) { + ConvertV1Profiles.addToConvertMsgs( + ConvertMsgFmt.REPORT_LINE | deleteMsgFormat, + `Deleted ${errMsgTrailer}.` + ); + } else { + ConvertV1Profiles.addToConvertMsgs( + ConvertMsgFmt.ERROR_LINE | deleteMsgFormat, + `Failed to delete ${errMsgTrailer}.` + ); + } + + // only start a new paragraph on our first delete message + deleteMsgFormat = 0; + } + } + } + } + } + + /** + * Convert a set of known property names to their new names + * for V2 conformance (and later releases). + * + * @param convertedConfig The converted client configuration in which we shall + * rename obsolete property names to their conformant names. + */ + private static convertPropNames(convertedConfig: IConfig): void { + const nameConversions = [ + ["hostname", "host"], + ["username", "user"], + ["pass", "password"] + ]; + + // iterate through all of the recorded profiles + for (const currProfNm of Object.keys(convertedConfig.profiles)) { + // iterate through the non-secure properties of the current profile + const profPropsToConvert = []; + const currProps = convertedConfig.profiles[currProfNm].properties; + for (const [currPropName, currPropVal] of Object.entries(currProps)) { + // iterate through the set of names that we must convert + for (const [oldPropName, newPropName] of nameConversions) { + if (currPropName === oldPropName) { + /* Store the property conversion info for later replacement. + * We do not want to add and delete properties while + * we are iterating the properties. + */ + const propToConvert = [oldPropName, newPropName, currPropVal]; + profPropsToConvert.push(propToConvert); + + /* We recorded the replacement for this property name. + * No need to look for more name conversions on this name. + */ + break; + } + } + } // end for all properties + + // convert the non-secure property names for the current profile + for (const [oldPropName, newPropName, propValue] of profPropsToConvert) { + delete currProps[oldPropName]; + currProps[newPropName] = propValue; + } + + // iterate through the secure property names of the current profile + const currSecProps = convertedConfig.profiles[currProfNm].secure; + for (let secInx = 0; secInx < currSecProps.length; secInx++) { + // iterate through the set of names that we must convert + for (const [oldPropName, newPropName] of nameConversions) { + if (currSecProps[secInx] === oldPropName) { + currSecProps[secInx] = newPropName; + + /* We replaced this secure property name. + * No need to look for more name conversions on this name. + */ + break; + } + } + } + } // end for all profiles + } // end convertPropNames + + /** + * Retrieve info about old plug-ins and their overrides. + * @returns IOldPluginInfo + * plugins - List of CLI plug-ins to uninstall + * overrides - List of overrides to replace in app settings + */ + private static getOldPluginInfo(): IOldPluginInfo { + const pluginInfo: IOldPluginInfo = { + plugins: [], + overrides: [] + }; + + // if the old SCS plugin is our credential manager, record that it should be replaced + let currCredMgr; + try { + // have AppSettings been initialized? + AppSettings.instance; + } catch (error) { + let settingsFile: string = "NotSetYet"; + try { + // A VSCode extension will not have initialized AppSettings, so initialize it now + settingsFile = path.join(ImperativeConfig.instance.cliHome, "settings", "imperative.json"); + const defaultSettings: ISettingsFile = { + overrides: {} + } as any; + defaultSettings.overrides[ConvertV1Profiles.credMgrKey] = ConvertV1Profiles.builtInCredMgrNm; + AppSettings.initialize(settingsFile, defaultSettings); + } catch(error) { + currCredMgr = null; + ConvertV1Profiles.addExceptionToConvertMsgs( + `Failed to initialize AppSettings overrides from ${settingsFile}.`, error + ); + } + } + + // get the current credMgr from AppSettings + try { + currCredMgr = AppSettings.instance.get("overrides", ConvertV1Profiles.credMgrKey); + } catch(error) { + currCredMgr = null; + ConvertV1Profiles.addExceptionToConvertMsgs( + `Failed trying to read '${ConvertV1Profiles.credMgrKey}' overrides.`, error + ); + } + + // we leave the 'false' indicator unchanged to allow for the use of no credMgr + if (typeof currCredMgr === "string") { + // if any of the old SCS credMgr names are found, record that we want to replace the credMgr + for (const oldOverrideName of [ + ConvertV1Profiles.oldScsPluginNm, "KeytarCredentialManager", "Zowe-Plugin", "Broadcom-Plugin"]) + { + if (currCredMgr.includes(oldOverrideName)) { + ConvertV1Profiles.oldScsPluginWasConfigured = true; + pluginInfo.overrides.push(ConvertV1Profiles.credMgrKey); + break; + } + } + } + + try { + // Only record the need to uninstall the SCS plug-in if it is currently installed + if (ConvertV1Profiles.isPluginInstalled(ConvertV1Profiles.oldScsPluginNm)) { + pluginInfo.plugins.push(ConvertV1Profiles.oldScsPluginNm); + } + } catch (error) { + // report all errors except the absence of the plugins.json file + if (!error.message.includes("ENOENT")) { + ConvertV1Profiles.addExceptionToConvertMsgs("Failed trying to get the set of installed plugins.", error); + } + } + + return pluginInfo; + } + + /** + * Report whether the specified plugin is installed. + * @param pluginName name of the plugin to search for. + * @returns True if plugin is installed. False otherwise. + */ + private static isPluginInstalled(pluginName: string): boolean { + let pluginsFileNm: string; + try { + pluginsFileNm = path.join(ImperativeConfig.instance.cliHome, "plugins", "plugins.json"); + const pluginsFileJson = readFileSync(pluginsFileNm); + if (Object.hasOwn(pluginsFileJson, pluginName)) { + return true; + } + } + catch (ioErr) { + // A VSCode extension may legitimately not have any plugins directory. + // However, something is wrong if the CLI does not have the plugins + // directory and file, so display the error. + if (!ConvertV1Profiles.profileInfo) { + ConvertV1Profiles.addExceptionToConvertMsgs(`Cannot read plugins file ${pluginsFileNm}`, ioErr); + } + } + return false; + } + + /** + * Get the number of old profiles present in the CLI home dir. + * @param profilesRootDir Root profiles directory + * @returns Number of old profiles found + */ + private static getOldProfileCount(profilesRootDir: string): number { + const profileTypes = V1ProfileRead.getAllProfileDirectories(profilesRootDir); + let oldProfileCount = 0; + for (const profileType of profileTypes) { + const profileTypeDir = path.join(profilesRootDir, profileType); + const profileNames = V1ProfileRead.getAllProfileNames(profileTypeDir, ".yaml", `${profileType}_meta`); + oldProfileCount += profileNames.length; + } + return oldProfileCount; + } + + /** + * Verify that the credential vault is accessible, or whether there is a problem. + * @returns true if credential vault is available, false if it is not + */ + private static async isZoweKeyRingAvailable(): Promise { + try { + ConvertV1Profiles.zoweKeyRing = (await import("@zowe/secrets-for-zowe-sdk")).keyring; + await ConvertV1Profiles.zoweKeyRing.findCredentials(CredentialManagerOverride.DEFAULT_CRED_MGR_NAME); + } catch (error) { + ConvertV1Profiles.addExceptionToConvertMsgs( + "Zowe keyring or the credential vault are unavailable. Unable to delete old secure values.", error + ); + return false; + } + return true; + } + + /** + * Locate the names of secured properties stored under an account in the operating + * system's credential vault. + * @param acct The account to search for in the credential store + * @param convertMsgs The set of conversion messages to which we can add new messages + * @returns a list of secured properties stored under the specified account + */ + private static async findOldSecureProps(acct: string): Promise { + const oldSecurePropNames: string[] = []; + try { + const credentialsArray = await ConvertV1Profiles.zoweKeyRing.findCredentials(acct); + for (const element of credentialsArray) { + oldSecurePropNames.push(element.account); + } + } catch (error) { + ConvertV1Profiles.convertResult.credsWereMigrated = false; + ConvertV1Profiles.addExceptionToConvertMsgs( + `Encountered an error while gathering secure properties for service '${acct}':`, error + ); + } + return oldSecurePropNames; + } + + /** + * Delete the secure property specified from the operating system credential vault. + * @param acct The account the property is stored under + * @param propName The name of the property to delete + * @param convertMsgs The set of conversion messages to which we can add new messages + * @returns true if the property was deleted successfully + */ + private static async deleteOldSecureProps(acct: string, propName: string): Promise { + let success = false; + try { + success = await ConvertV1Profiles.zoweKeyRing.deletePassword(acct, propName); + } catch (error) { + ConvertV1Profiles.addExceptionToConvertMsgs( + `Encountered an error while deleting secure data for service '${acct}/${propName}':`, error + ); + success = false; + } + return success; + } + + /** + * Add a new message to the V1 profile conversion messages that reports a caught exception. + * + * @param introMsg An introductory message describing what action was being attempted when we failed. + * @param error The exception that we caught. + */ + private static addExceptionToConvertMsgs(introMsg: string, error: Error): void { + ConvertV1Profiles.addToConvertMsgs(ConvertMsgFmt.ERROR_LINE | ConvertMsgFmt.PARAGRAPH, introMsg); + ConvertV1Profiles.addToConvertMsgs(ConvertMsgFmt.ERROR_LINE | ConvertMsgFmt.INDENT, "Reason: " + stripAnsi(error.message)); + if (Object.hasOwn(error, "stack")) { + ConvertV1Profiles.addToConvertMsgs(ConvertMsgFmt.ERROR_LINE | ConvertMsgFmt.INDENT, stripAnsi(error.stack)); + } + } + + /** + * Add a new message to the V1 profile conversion messages. + * @param msgFormat Formatting clues for the message. + * @param msgText Unformatted text of the message. + */ + private static addToConvertMsgs(msgFormat: number, msgText: string): void { + if (msgFormat & ConvertMsgFmt.ERROR_LINE) { + Logger.getImperativeLogger().error(msgText); + } + const newMsg = new ConvertMsg(msgFormat, msgText); + ConvertV1Profiles.convertResult.msgs.push(newMsg); + } +} diff --git a/packages/imperative/src/config/src/ProfileCredentials.ts b/packages/imperative/src/config/src/ProfileCredentials.ts index 78e5f3e24c..bb97d4ac57 100644 --- a/packages/imperative/src/config/src/ProfileCredentials.ts +++ b/packages/imperative/src/config/src/ProfileCredentials.ts @@ -23,7 +23,7 @@ export class ProfileCredentials { private mCredMgrOverride?: ICredentialManagerInit; constructor(private mProfileInfo: ProfileInfo, opts?: IProfOpts | (() => NodeModule)) { - this.mCredMgrOverride = (typeof opts === "function") ? ProfileCredentials.defaultCredMgrWithKeytar(opts) : opts?.credMgrOverride; + this.mCredMgrOverride = typeof opts === "function" ? ProfileCredentials.defaultCredMgrWithKeytar(opts) : opts?.credMgrOverride; } /** @@ -78,25 +78,23 @@ export class ProfileCredentials { try { // TODO? Make CredentialManagerFactory.initialize params optional // see https://github.com/zowe/imperative/issues/545 - await CredentialManagerFactory.initialize({ service: null, ...(this.mCredMgrOverride || {}) }); + await CredentialManagerFactory.initialize({ service: null, ...this.mCredMgrOverride || {} }); } catch (error) { - throw (error instanceof ImperativeError) ? error : new ImperativeError({ + throw error instanceof ImperativeError ? error : new ImperativeError({ msg: `Failed to load CredentialManager class: ${error.message}`, causeErrors: error }); } } - if (this.mProfileInfo.usingTeamConfig) { - await this.mProfileInfo.getTeamConfig().api.secure.load({ - load: ((key: string): Promise => { - return CredentialManagerFactory.manager.load(key, true); - }), - save: ((key: string, value: any): Promise => { - return CredentialManagerFactory.manager.save(key, value); - }) - }); - } + await this.mProfileInfo.getTeamConfig().api.secure.load({ + load: (key: string): Promise => { + return CredentialManagerFactory.manager.load(key, true); + }, + save: (key: string, value: any): Promise => { + return CredentialManagerFactory.manager.save(key, value); + } + }); } /** @@ -104,7 +102,6 @@ export class ProfileCredentials { * @returns False if not using teamConfig or there are no secure fields */ private isTeamConfigSecure(): boolean { - if (!this.mProfileInfo.usingTeamConfig) return false; if (this.mProfileInfo.getTeamConfig().api.secure.secureFields().length === 0) return false; return true; } @@ -122,7 +119,7 @@ export class ProfileCredentials { } const value1 = settings?.overrides.CredentialManager; const value2 = settings?.overrides["credential-manager"]; - return (typeof value1 === "string" && value1.length > 0) || (typeof value2 === "string" && value2.length > 0); + return typeof value1 === "string" && value1.length > 0 || typeof value2 === "string" && value2.length > 0; } catch (error) { throw new ImperativeError({ msg: "Unable to read Imperative settings file", diff --git a/packages/imperative/src/config/src/ProfileInfo.ts b/packages/imperative/src/config/src/ProfileInfo.ts index ec35a9f5d6..3b6824e1e8 100644 --- a/packages/imperative/src/config/src/ProfileInfo.ts +++ b/packages/imperative/src/config/src/ProfileInfo.ts @@ -10,15 +10,13 @@ */ import * as fs from "fs"; -import * as os from "os"; -import * as path from "path"; import * as url from "url"; import * as jsonfile from "jsonfile"; import * as lodash from "lodash"; import * as semver from "semver"; // for ProfileInfo structures -import { IProfArgAttrs } from "./doc/IProfArgAttrs"; +import { IProfArgAttrs, IProfDataType } from "./doc/IProfArgAttrs"; import { IProfAttrs } from "./doc/IProfAttrs"; import { IArgTeamConfigLoc, IProfLoc, IProfLocOsLoc, IProfLocOsLocLayer, ProfLocType } from "./doc/IProfLoc"; import { IProfMergeArgOpts } from "./doc/IProfMergeArgOpts"; @@ -33,18 +31,14 @@ import { Config } from "./Config"; import { ConfigSchema } from "./ConfigSchema"; import { IConfigOpts } from "./doc/IConfigOpts"; -// for old-school profile operations -import { AbstractProfileManager } from "../../profiles/src/abstract/AbstractProfileManager"; -import { CliProfileManager, ICommandProfileProperty, ICommandArguments } from "../../cmd"; -import { IProfileLoaded, IProfileProperty, IProfileSchema, ProfileIO } from "../../profiles"; +import { ICommandProfileProperty, ICommandArguments } from "../../cmd"; +import { IProfileLoaded, IProfileProperty, IProfileSchema } from "../../profiles"; // for imperative operations -import { EnvironmentalVariableSettings } from "../../imperative/src/env/EnvironmentalVariableSettings"; -import { LoggingConfigurer } from "../../imperative/src/LoggingConfigurer"; import { CliUtils, ImperativeConfig } from "../../utilities"; import { ImperativeExpect } from "../../expect"; -import { Logger, LoggerUtils } from "../../logger"; -import { LoggerManager } from "../../logger/src/LoggerManager"; +import { Logger } from "../../logger"; +import { LoggerUtils } from "../../logger/src/LoggerUtils"; import { IOptionsForAddConnProps, ISession, Session, SessConstants, ConnectionPropsForSessCfg } from "../../rest"; @@ -126,9 +120,7 @@ import { Constants } from "../../constants"; * youRunSomeZosmfCommand(finalZosmfArgs); * } * - * // So you want to write to a config file? You must use your own - * // old-school techniques to write to old-school profiles. - * // You then use alternate logic for a team config. + * // So you want to write to a config file? * // You must use the Config API to write to a team configuration. * // See the Config class documentation for functions to set * // and save team config arguments. @@ -138,33 +130,24 @@ import { Constants } from "../../constants"; * youSetValuesToOverwrite( * zosmfMergedArgs.knownArgs, zosmfMergedArgs.missingArgs * ); - * if (profInfo.usingTeamConfig { - * let configObj: Config = profInfo.getTeamConfig(); - * youWriteArgValuesUsingConfigObj( - * configObj, yourZosmfArgsToWrite - * ); - * } else { - * youWriteOldSchoolProfiles(yourZosmfArgsToWrite); - * } + * + * let configObj: Config = profInfo.getTeamConfig(); + * youWriteArgValuesUsingConfigObj( + * configObj, yourZosmfArgsToWrite + * ); * */ export class ProfileInfo { private mLoadedConfig: Config = null; - private mUsingTeamConfig: boolean = false; private mAppName: string = null; private mImpLogger: Logger = null; - private mOldSchoolProfileCache: IProfileLoaded[] = null; - private mOldSchoolProfileRootDir: string = null; - private mOldSchoolProfileDefaults: { [key: string]: string } = null; - private mOldSchoolProfileTypes: string[]; private mOverrideWithEnv: boolean = false; private mHasValidSchema: boolean = false; /** * Cache of profile schema objects mapped by profile type and config path - * if applicable. Examples of map keys: + * if applicable. Example of map keys: * - For team config: "/root/.zowe/zowe.config.json:zosmf" - * - For old profiles: "zosmf" */ private mProfileSchemaCache: Map; private mCredentials: ProfileCredentials; @@ -190,16 +173,14 @@ export class ProfileInfo { this.mOverrideWithEnv = profInfoOpts.overrideWithEnv; } - // eslint-disable-next-line deprecation/deprecation - this.mCredentials = new ProfileCredentials(this, profInfoOpts?.requireKeytar ?? profInfoOpts); + this.mCredentials = new ProfileCredentials(this, profInfoOpts); // do enough Imperative stuff to let imperative utilities work - this.initImpUtils(); + this.mImpLogger = ConfigUtils.initImpUtils(this.mAppName); } /** - * Update a given property regardless of whether it's found in the config file or not - * This function supports v1 profiles + * Update a given property in the config file. * @param options Set of options needed to update a given property */ public async updateProperty(options: IProfInfoUpdatePropOpts): Promise { @@ -209,8 +190,8 @@ export class ProfileInfo { let updated = false; if (desiredProfile != null) { const mergedArgs = this.mergeArgsForProfile(desiredProfile, { getSecureVals: false }); - if (options.forceUpdate && this.usingTeamConfig) { - const knownProperty = mergedArgs.knownArgs.find((v => v.argName === options.property)); + if (options.forceUpdate) { + const knownProperty = mergedArgs.knownArgs.find(v => v.argName === options.property); if (knownProperty != null) { const profPath = this.getTeamConfig().api.profiles.getProfilePathFromName(options.profileName); if (!ConfigUtils.jsonPathMatches(knownProperty.argLoc.jsonLoc, profPath)) { @@ -219,8 +200,7 @@ export class ProfileInfo { } } updated = await this.updateKnownProperty({ ...options, mergedArgs, osLocInfo: this.getOsLocInfo(desiredProfile)?.[0] }); - } else if (!(this.usingTeamConfig && options.profileType == null && - (options.forceUpdate || this.getTeamConfig().api.profiles.exists(options.profileName)))) { + } else if (!(options.profileType == null && (options.forceUpdate || this.getTeamConfig().api.profiles.exists(options.profileName)))) { throw new ProfInfoErr({ errorCode: ProfInfoErr.PROF_NOT_FOUND, msg: `Failed to find profile ${options.profileName} of type ${options.profileType}` @@ -228,43 +208,34 @@ export class ProfileInfo { } if (!updated) { - if (this.usingTeamConfig) { - // Check to see if loadedConfig already contains the schema for the specified profile type - if (ImperativeConfig.instance.loadedConfig?.profiles?.find(p => p.type === options.profileType)?.schema == null || - ImperativeConfig.instance.loadedConfig?.baseProfile?.schema == null) { - - const loadedConfig = ImperativeConfig.instance.loadedConfig; - if (!loadedConfig.profiles) loadedConfig.profiles = []; - this.mProfileSchemaCache.forEach((value: IProfileSchema, key: string) => { - if (key.indexOf(":base") > 0 && loadedConfig.baseProfile == null) { - loadedConfig.baseProfile = { type: "base", schema: value }; - } else if (key.indexOf(":base") < 0 && !loadedConfig.profiles.find(p => p.type === key.split(":")[1])) { - // Add the schema corresponding to the given profile type - loadedConfig.profiles.push({ type: key.split(":")[1], schema: value }); - } - }); - ImperativeConfig.instance.loadedConfig = loadedConfig; - } - - await ConfigAutoStore._storeSessCfgProps({ - config: this.mLoadedConfig, - defaultBaseProfileName: this.mLoadedConfig?.mProperties.defaults.base, - sessCfg: { - [options.property === "host" ? "hostname" : options.property]: options.value - }, - propsToStore: [options.property], - profileName: options.profileName, - profileType: options.profileType, - setSecure: options.setSecure + // Check to see if loadedConfig already contains the schema for the specified profile type + if (ImperativeConfig.instance.loadedConfig?.profiles?.find(p => p.type === options.profileType)?.schema == null || + ImperativeConfig.instance.loadedConfig?.baseProfile?.schema == null) { + + const loadedConfig = ImperativeConfig.instance.loadedConfig; + if (!loadedConfig.profiles) loadedConfig.profiles = []; + this.mProfileSchemaCache.forEach((value: IProfileSchema, key: string) => { + if (key.indexOf(":base") > 0 && loadedConfig.baseProfile == null) { + loadedConfig.baseProfile = { type: "base", schema: value }; + } else if (key.indexOf(":base") < 0 && !loadedConfig.profiles.find(p => p.type === key.split(":")[1])) { + // Add the schema corresponding to the given profile type + loadedConfig.profiles.push({ type: key.split(":")[1], schema: value }); + } }); - } else { - const profMgr = new CliProfileManager({ profileRootDirectory: this.mOldSchoolProfileRootDir, type: options.profileType }); - // Add new property - await profMgr.update({ name: options.profileName, merge: true, profile: { [options.property]: options.value } }); - - // Update mOldSchoolProfileCache to get mergedArgs updated - this.mOldSchoolProfileCache.find(v => v.name === options.profileName).profile[options.property] = options.value; + ImperativeConfig.instance.loadedConfig = loadedConfig; } + + await ConfigAutoStore._storeSessCfgProps({ + config: this.mLoadedConfig, + defaultBaseProfileName: this.mLoadedConfig?.mProperties.defaults.base, + sessCfg: { + [options.property === "host" ? "hostname" : options.property]: options.value + }, + propsToStore: [options.property], + profileName: options.profileName, + profileType: options.profileType, + setSecure: options.setSecure + }); } } @@ -272,40 +243,18 @@ export class ProfileInfo { * Update a given property with the value provided. * This function only works for properties that can be found in the config files (including secure arrays). * If the property cannot be found, this function will resolve to false - * This function supports v1 profiles * @param options Set of options required to update a known property */ public async updateKnownProperty(options: IProfInfoUpdateKnownPropOpts): Promise { this.ensureReadFromDisk(); - const toUpdate = options.mergedArgs.knownArgs.find((v => v.argName === options.property)) || - options.mergedArgs.missingArgs.find((v => v.argName === options.property)); + const toUpdate = options.mergedArgs.knownArgs.find(v => v.argName === options.property) || + options.mergedArgs.missingArgs.find(v => v.argName === options.property); - if (toUpdate == null || (toUpdate.argLoc.locType === ProfLocType.TEAM_CONFIG && !this.getTeamConfig().mProperties.autoStore)) { + if (toUpdate == null || toUpdate.argLoc.locType === ProfLocType.TEAM_CONFIG && !this.getTeamConfig().mProperties.autoStore) { return false; } switch (toUpdate.argLoc.locType) { - case ProfLocType.OLD_PROFILE: { - const filePath = toUpdate.argLoc.osLoc; - const profileName = ProfileIO.fileToProfileName(filePath[0], "." + filePath[0].split(".").slice(-1)[0]); - const profileType = filePath[0].substring(this.mOldSchoolProfileRootDir.length + 1).split(path.sep)[0]; - const profMgr = new CliProfileManager({ profileRootDirectory: this.mOldSchoolProfileRootDir, type: profileType }); - if (options.value !== undefined) { - await profMgr.update({ name: profileName, merge: true, profile: { [options.property]: options.value } }); - } else { - // Remove existing property (or don't do anything) - const oldProf = await profMgr.load({ name: profileName, failNotFound: false }); - if (oldProf && oldProf.profile && oldProf.profile[options.property]) { - delete oldProf.profile[options.property]; - await profMgr.save({ name: profileName, profile: oldProf.profile, overwrite: true, type: profileType }); - } - } - - // Update mOldSchoolProfileCache to get mergedArgs updated - const profile = this.mOldSchoolProfileCache.find(v => v.name === profileName); - if (profile != null) profile.profile[options.property] = options.value; // What should we do in the else case? - break; - } case ProfLocType.TEAM_CONFIG: { let oldLayer: IProfLocOsLocLayer; const layer = this.getTeamConfig().layerActive(); @@ -328,9 +277,13 @@ export class ProfileInfo { case ProfLocType.DEFAULT: return false; default: { + let msgText = "Invalid profile location type: "; + if (toUpdate.argLoc.locType == ProfLocType.OLD_PROFILE) { + msgText = "You can no longer write to V1 profiles. Location type = "; + } throw new ProfInfoErr({ errorCode: ProfInfoErr.INVALID_PROF_LOC_TYPE, - msg: "Invalid profile location type: " + toUpdate.argLoc.locType + msg: msgText + toUpdate.argLoc.locType }); } } @@ -386,52 +339,32 @@ export class ProfileInfo { const profiles: IProfAttrs[] = []; // Do we have team config profiles? - if (this.mUsingTeamConfig) { - const teamConfigProfs = this.mLoadedConfig.layerMerge({ maskSecure: true, excludeGlobalLayer: options?.excludeHomeDir }).profiles; - // Iterate over them - for (const prof in teamConfigProfs) { - // Check if the profile has a type - if (teamConfigProfs[prof].type && (profileType == null || teamConfigProfs[prof].type === profileType)) { - const jsonLocation: string = "profiles." + prof; - const teamOsLocation: string[] = this.findTeamOsLocation(jsonLocation, options?.excludeHomeDir); - const profAttrs: IProfAttrs = { - profName: prof, - profType: teamConfigProfs[prof].type, - isDefaultProfile: this.isDefaultTeamProfile(prof, profileType), - profLoc: { - locType: ProfLocType.TEAM_CONFIG, - osLoc: teamOsLocation, - jsonLoc: jsonLocation - } - }; - profiles.push(profAttrs); - } - // Check for subprofiles - if (teamConfigProfs[prof].profiles) { - // Get the subprofiles and add to profiles list - const jsonPath = "profiles." + prof; - const subProfiles: IProfAttrs[] = this.getTeamSubProfiles(prof, jsonPath, teamConfigProfs[prof].profiles, profileType); - for (const subProfile of subProfiles) { - profiles.push(subProfile); + const teamConfigProfs = this.mLoadedConfig.layerMerge({ maskSecure: true, excludeGlobalLayer: options?.excludeHomeDir }).profiles; + // Iterate over them + for (const prof in teamConfigProfs) { + // Check if the profile has a type + if (teamConfigProfs[prof].type && (profileType == null || teamConfigProfs[prof].type === profileType)) { + const jsonLocation: string = "profiles." + prof; + const teamOsLocation: string[] = this.findTeamOsLocation(jsonLocation, options?.excludeHomeDir); + const profAttrs: IProfAttrs = { + profName: prof, + profType: teamConfigProfs[prof].type, + isDefaultProfile: this.isDefaultTeamProfile(prof, profileType), + profLoc: { + locType: ProfLocType.TEAM_CONFIG, + osLoc: teamOsLocation, + jsonLoc: jsonLocation } - } + }; + profiles.push(profAttrs); } - } else { - for (const loadedProfile of this.mOldSchoolProfileCache) { - if (!profileType || profileType === loadedProfile.type) { - const typeDefaultProfile = this.getDefaultProfile(loadedProfile.type); - let defaultProfile = false; - if (typeDefaultProfile && typeDefaultProfile.profName === loadedProfile.name) { defaultProfile = true; } - profiles.push({ - profName: loadedProfile.name, - profType: loadedProfile.type, - isDefaultProfile: defaultProfile, - profLoc: { - locType: ProfLocType.OLD_PROFILE, - osLoc: [this.oldProfileFilePath(loadedProfile.type, loadedProfile.name)], - jsonLoc: undefined - } - }); + // Check for subprofiles + if (teamConfigProfs[prof].profiles) { + // Get the subprofiles and add to profiles list + const jsonPath = "profiles." + prof; + const subProfiles: IProfAttrs[] = this.getTeamSubProfiles(prof, jsonPath, teamConfigProfs[prof].profiles, profileType); + for (const subProfile of subProfiles) { + profiles.push(subProfile); } } } @@ -460,71 +393,30 @@ export class ProfileInfo { } }; - if (this.usingTeamConfig) { - // get default profile name from the team config - const configProperties = this.mLoadedConfig.mProperties; - if (!Object.prototype.hasOwnProperty.call(configProperties.defaults, profileType)) { - // no default exists for the requested type - this.mImpLogger.warn("Found no profile of type '" + - profileType + "' in team config." - ); - return null; - } - - // extract info from the underlying team config - const foundProfNm = configProperties.defaults[profileType]; - - // for a team config, we use the last node of the jsonLoc as the name - const foundJson = this.mLoadedConfig.api.profiles.getProfilePathFromName(foundProfNm); - const teamOsLocation: string[] = this.findTeamOsLocation(foundJson); - - // assign the required poperties to defaultProfile - defaultProfile.profName = foundProfNm; - defaultProfile.profLoc = { - locType: ProfLocType.TEAM_CONFIG, - osLoc: teamOsLocation, - jsonLoc: foundJson - }; - } else { - // get default profile from the old-school profiles - // first, some validation - if (!this.mOldSchoolProfileCache || this.mOldSchoolProfileCache.length === 0) { - // No old school profiles in the cache - warn and return null - this.mImpLogger.warn("Found no old-school profiles."); - return null; - } - if (!this.mOldSchoolProfileDefaults || Object.keys(this.mOldSchoolProfileDefaults).length === 0) { - // No old-school default profiles found - warn and return null - this.mImpLogger.warn("Found no default old-school profiles."); - return null; - } - - const profName = this.mOldSchoolProfileDefaults[profileType]; - if (!profName) { - // No old-school default profile of this type - warn and return null - this.mImpLogger.warn("Found no old-school profile for type '" + profileType + "'."); - return null; - } + // get default profile name from the team config + const configProperties = this.mLoadedConfig.mProperties; + if (!Object.prototype.hasOwnProperty.call(configProperties.defaults, profileType)) { + // no default exists for the requested type + this.mImpLogger.warn("Found no profile of type '" + + profileType + "' in Zowe client configuration." + ); + return null; + } - const loadedProfile = this.mOldSchoolProfileCache.find(obj => { - return obj.name === profName && obj.type === profileType; - }); - if (!loadedProfile) { - // Something really weird happened - this.mImpLogger.warn(`Profile with name '${profName}' was defined as the default profile for type '${profileType}' but was missing ` + - `from the cache.`); - return null; - } + // extract info from the underlying team config + const foundProfNm = configProperties.defaults[profileType]; - ImperativeExpect.toBeEqual(loadedProfile.type, profileType); + // for a team config, we use the last node of the jsonLoc as the name + const foundJson = this.mLoadedConfig.api.profiles.getProfilePathFromName(foundProfNm); + const teamOsLocation: string[] = this.findTeamOsLocation(foundJson); - // assign the required properties to defaultProfile - defaultProfile.profName = loadedProfile.name; - defaultProfile.profLoc = { - locType: ProfLocType.OLD_PROFILE, - osLoc: [this.oldProfileFilePath(profileType, loadedProfile.name)] - }; - } + // assign the required poperties to defaultProfile + defaultProfile.profName = foundProfNm; + defaultProfile.profLoc = { + locType: ProfLocType.TEAM_CONFIG, + osLoc: teamOsLocation, + jsonLoc: foundJson + }; return defaultProfile; } @@ -691,49 +583,6 @@ export class ProfileInfo { } } } - } else if (profile.profLoc.locType === ProfLocType.OLD_PROFILE) { - if (profile.profName != null) { - const serviceProfile = this.mOldSchoolProfileCache.find(obj => { - return obj.name === profile.profName && obj.type === profile.profType; - })?.profile; - if (serviceProfile != null) { - // Load args from service profile if one exists - for (const [propName, propVal] of Object.entries(serviceProfile)) { - // Skip undefined properties because they don't meet criteria for known args - if (propVal === undefined) continue; - mergedArgs.knownArgs.push({ - argName: CliUtils.getOptionFormat(propName).camelCase, - dataType: this.argDataType(typeof propVal), - argValue: propVal, - argLoc: this.argOldProfileLoc(profile.profName, profile.profType) - }); - } - } - } - - const baseProfileName = this.mOldSchoolProfileDefaults.base; - if (baseProfileName != null) { - // Load args from default base profile if one exists - const baseProfile = this.mOldSchoolProfileCache.find(obj => { - return obj.name === baseProfileName && obj.type === "base"; - })?.profile; - if (baseProfile != null) { - for (const [propName, propVal] of Object.entries(baseProfile)) { - // Skip undefined properties because they don't meet criteria for known args - if (propVal === undefined) continue; - const argName = CliUtils.getOptionFormat(propName).camelCase; - // Skip properties already loaded from service profile - if (!mergedArgs.knownArgs.find((arg) => arg.argName === argName)) { - mergedArgs.knownArgs.push({ - argName, - dataType: this.argDataType(typeof propVal), - argValue: propVal, - argLoc: this.argOldProfileLoc(baseProfileName, "base") - }); - } - } - } - } } else { throw new ProfInfoErr({ errorCode: ProfInfoErr.INVALID_PROF_LOC_TYPE, @@ -874,12 +723,35 @@ export class ProfileInfo { profName: null, profType: profileType, isDefaultProfile: false, - profLoc: { locType: this.mUsingTeamConfig ? ProfLocType.TEAM_CONFIG : ProfLocType.OLD_PROFILE } + profLoc: { locType: ProfLocType.TEAM_CONFIG } }, mergeOpts ); } + /** + * Retrieves the Zowe CLI home directory. In the situation Imperative has + * not initialized it we use a default value. + * @returns {string} - Returns the Zowe home directory + * @deprecated Use ConfigUtils.getZoweDir() + */ + public static getZoweDir(): string { + return ConfigUtils.getZoweDir(); + } + + /** + * Returns an indicator that the user has no team configuration, but we + * detected the existence of old-school V1 profiles. We will not work with the + * V1 profiles. This function can let you tell a user that they are incorrectly + * trying to use V1 profiles. + * + * @returns True - Means there is *NO* team config *AND* we detected that a V1 profile exists. + * False otherwise. + */ + public static get onlyV1ProfilesExist(): boolean { + return ConfigUtils.onlyV1ProfilesExist; + } + // _______________________________________________________________________ /** * Convert an IProfAttrs object into an IProfileLoaded objects @@ -941,17 +813,13 @@ export class ProfileInfo { // _______________________________________________________________________ /** - * Read either the new team configuration files (if any exist) or - * read the old-school profile files. + * Read the team configuration files (if any exist). * * @param teamCfgOpts - * The optional choices used when reading a team configuration. - * This parameter is ignored, if the end-user is using old-school - * profiles. + * The optional choices related to reading a team configuration. */ public async readProfilesFromDisk(teamCfgOpts?: IConfigOpts) { this.mLoadedConfig = await Config.load(this.mAppName, { homeDir: ImperativeConfig.instance.cliHome, ...teamCfgOpts }); - this.mUsingTeamConfig = this.mLoadedConfig.exists; try { if (this.mCredentials.isSecured) { @@ -965,41 +833,7 @@ export class ProfileInfo { }); } - if (!this.mUsingTeamConfig) { - // Clear out the values - this.mOldSchoolProfileCache = []; - this.mOldSchoolProfileDefaults = {}; - // Try to get profiles and types - this.mOldSchoolProfileRootDir = path.join(ImperativeConfig.instance.cliHome, "profiles"); - this.mOldSchoolProfileTypes = fs.existsSync(this.mOldSchoolProfileRootDir) ? - ProfileIO.getAllProfileDirectories(this.mOldSchoolProfileRootDir) : []; - // Iterate over the types - for (const profType of this.mOldSchoolProfileTypes) { - // Set up the profile manager and list of profile names - const profileManager = new CliProfileManager({ profileRootDirectory: this.mOldSchoolProfileRootDir, type: profType }); - const profileList = profileManager.getAllProfileNames(); - // Iterate over them all - for (const prof of profileList) { - // Load and add to the list - try { - const loadedProfile = await profileManager.load({ name: prof }); - this.mOldSchoolProfileCache.push(loadedProfile); - } catch (err) { - this.mImpLogger.warn(err.message); - } - } - - try { - const defaultProfile = await profileManager.load({ loadDefault: true }); - if (defaultProfile) { this.mOldSchoolProfileDefaults[profType] = defaultProfile.name; } - } catch (err) { - this.mImpLogger.warn(err.message); - } - } - } else { - this.mExtendersJson = ProfileInfo.readExtendersJsonFromDisk(); - } - + this.mExtendersJson = ConfigUtils.readExtendersJson(); this.loadAllSchemas(); } @@ -1022,20 +856,6 @@ export class ProfileInfo { } } - // _______________________________________________________________________ - /** - * Returns an indicator of whether we are using a team configuration or - * old-school profiles. - * - * You must call ProfileInfo.readProfilesFromDisk() before calling this function. - * - * @returns True when we are using a team config. False means old-school profiles. - */ - public get usingTeamConfig(): boolean { - this.ensureReadFromDisk(); - return this.mUsingTeamConfig; - } - /** * Returns whether a valid schema was found (works for v1 and v2 configs) */ @@ -1086,18 +906,6 @@ export class ProfileInfo { } } break; - case ProfLocType.OLD_PROFILE: - if (arg.argLoc.osLoc?.length > 0) { - for (const loadedProfile of this.mOldSchoolProfileCache) { - const profilePath = this.oldProfileFilePath(loadedProfile.type, loadedProfile.name); - if (profilePath === arg.argLoc.osLoc[0]) { - // we found the loaded profile matching arg.osLoc - argValue = loadedProfile.profile[arg.argName]; - break; - } - } - } - break; default: // not stored securely if location is ENV or DEFAULT argValue = arg.argValue; } @@ -1173,105 +981,49 @@ export class ProfileInfo { } } - // _______________________________________________________________________ - /** - * Perform a rudimentary initialization of some Imperative utilities. - * We must do this because VSCode apps do not typically call imperative.init. - */ - private initImpUtils() { - // create a rudimentary ImperativeConfig if it has not been initialized - if (ImperativeConfig.instance.loadedConfig == null) { - let homeDir: string = null; - const envVarPrefix = this.mAppName.toUpperCase(); - const envVarNm = envVarPrefix + EnvironmentalVariableSettings.CLI_HOME_SUFFIX; - if (process.env[envVarNm] === undefined) { - // use OS home directory - homeDir = path.join(os.homedir(), "." + this.mAppName.toLowerCase()); - } else { - // use the available environment variable - homeDir = path.normalize(process.env[envVarNm]); - } - ImperativeConfig.instance.loadedConfig = { - name: this.mAppName, - defaultHome: homeDir, - envVariablePrefix: envVarPrefix - }; - ImperativeConfig.instance.rootCommandName = this.mAppName; - } - - // initialize logging - if (LoggerManager.instance.isLoggerInit === false) { - const loggingConfig = LoggingConfigurer.configureLogger( - ImperativeConfig.instance.cliHome, ImperativeConfig.instance.loadedConfig - ); - Logger.initLogger(loggingConfig); - } - this.mImpLogger = Logger.getImperativeLogger(); - } - /** * Load any profile schema objects found on disk and cache them. For team * config, we check each config layer and load its schema JSON if there is - * one associated. For old school profiles, we load the meta YAML file for - * each profile type if it exists in the profile root directory. + * one associated. */ private loadAllSchemas(): void { this.mProfileSchemaCache = new Map(); - if (this.mUsingTeamConfig) { - // Load profile schemas for all layers - let lastSchema: { path: string, json: any } = { path: null, json: null }; - for (const layer of this.getTeamConfig().mLayers) { - if (layer.properties.$schema == null) continue; - const schemaUri = new url.URL(layer.properties.$schema, url.pathToFileURL(layer.path)); - if (schemaUri.protocol !== "file:") { - throw new ProfInfoErr({ - errorCode: ProfInfoErr.CANT_GET_SCHEMA_URL, - msg: `Failed to load schema for config file ${layer.path}: web URLs are not supported by ProfileInfo API` - }); - } - const schemaPath = url.fileURLToPath(schemaUri); - if (fs.existsSync(schemaPath)) { - try { - let schemaJson; - if (schemaPath !== lastSchema.path) { - schemaJson = jsonfile.readFileSync(schemaPath); - lastSchema = { path: schemaPath, json: schemaJson }; - } else { - schemaJson = lastSchema.json; - } - for (const { type, schema } of ConfigSchema.loadSchema(schemaJson)) { - this.mProfileSchemaCache.set(`${layer.path}:${type}`, schema); - } - } catch (error) { - throw new ProfInfoErr({ - errorCode: ProfInfoErr.LOAD_SCHEMA_FAILED, - msg: `Failed to load schema for config file ${layer.path}: invalid schema file`, - causeErrors: error - }); - } - } - } - this.mHasValidSchema = lastSchema.path != null; - } else { - // Load profile schemas from meta files in profile root dir - for (const type of this.mOldSchoolProfileTypes) { - const metaPath = this.oldProfileFilePath(type, type + AbstractProfileManager.META_FILE_SUFFIX); - if (fs.existsSync(metaPath)) { - this.mHasValidSchema = true; - try { - const metaProfile = ProfileIO.readMetaFile(metaPath); - this.mProfileSchemaCache.set(type, metaProfile.configuration.schema); - } catch (error) { - throw new ProfInfoErr({ - errorCode: ProfInfoErr.LOAD_SCHEMA_FAILED, - msg: `Failed to load schema for profile type ${type}: invalid meta file`, - causeErrors: error - }); + // Load profile schemas for all layers + let lastSchema: { path: string, json: any } = { path: null, json: null }; + for (const layer of this.getTeamConfig().mLayers) { + if (layer.properties.$schema == null) continue; + const schemaUri = new url.URL(layer.properties.$schema, url.pathToFileURL(layer.path)); + if (schemaUri.protocol !== "file:") { + throw new ProfInfoErr({ + errorCode: ProfInfoErr.CANT_GET_SCHEMA_URL, + msg: `Failed to load schema for config file ${layer.path}: web URLs are not supported by ProfileInfo API` + }); + } + const schemaPath = url.fileURLToPath(schemaUri); + if (fs.existsSync(schemaPath)) { + try { + let schemaJson; + if (schemaPath !== lastSchema.path) { + schemaJson = jsonfile.readFileSync(schemaPath); + lastSchema = { path: schemaPath, json: schemaJson }; + } else { + schemaJson = lastSchema.json; + } + for (const { type, schema } of ConfigSchema.loadSchema(schemaJson)) { + this.mProfileSchemaCache.set(`${layer.path}:${type}`, schema); } + } catch (error) { + throw new ProfInfoErr({ + errorCode: ProfInfoErr.LOAD_SCHEMA_FAILED, + msg: `Failed to load schema for config file ${layer.path}: invalid schema file`, + causeErrors: error + }); } } } + + this.mHasValidSchema = lastSchema.path != null; LoggerUtils.setProfileSchemas(this.mProfileSchemaCache); } @@ -1279,33 +1031,20 @@ export class ProfileInfo { * Reads the `extenders.json` file from the CLI home directory. * Called once in `readProfilesFromDisk` and cached to minimize I/O operations. * @internal + * @deprecated Please use `ConfigUtils.readExtendersJson` instead */ public static readExtendersJsonFromDisk(): IExtendersJsonOpts { - const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); - if (!fs.existsSync(extenderJsonPath)) { - jsonfile.writeFileSync(extenderJsonPath, { - profileTypes: {} - }, { spaces: 4 }); - return { profileTypes: {} }; - } else { - return jsonfile.readFileSync(extenderJsonPath); - } + return ConfigUtils.readExtendersJson(); } /** * Attempts to write to the `extenders.json` file in the CLI home directory. * @returns `true` if written successfully; `false` otherwise * @internal + * @deprecated Please use `ConfigUtils.writeExtendersJson` instead */ public static writeExtendersJson(obj: IExtendersJsonOpts): boolean { - try { - const extenderJsonPath = path.join(ImperativeConfig.instance.cliHome, "extenders.json"); - jsonfile.writeFileSync(extenderJsonPath, obj, { spaces: 4 }); - } catch (err) { - return false; - } - - return true; + return ConfigUtils.writeExtendersJson(obj); } /** @@ -1431,7 +1170,7 @@ export class ProfileInfo { if (semver.major(typeInfo.schema.version) != semver.major(prevTypeVersion)) { // Warn user if new major schema version is specified infoMsg = - `Profile type ${profileType} was updated from schema version ${prevTypeVersion} to ${typeInfo.schema.version}.\n` + + `Profile type ${profileType} was updated from schema version ${prevTypeVersion} to ${typeInfo.schema.version}.\n` + `The following applications may be affected: ${typeMetadata.from.filter((src) => src !== typeInfo.sourceApp)}`; } } else if (semver.major(prevTypeVersion) > semver.major(typeInfo.schema.version)) { @@ -1527,7 +1266,7 @@ export class ProfileInfo { // Update contents of extenders.json if it has changed if (wasGlobalUpdated && !lodash.isEqual(oldExtendersJson, this.mExtendersJson)) { - if (!ProfileInfo.writeExtendersJson(this.mExtendersJson)) { + if (!ConfigUtils.writeExtendersJson(this.mExtendersJson)) { return { success: true, // Even if we failed to update extenders.json, it was technically added to the schema cache. @@ -1649,6 +1388,65 @@ export class ProfileInfo { return finalSchema; } + // _______________________________________________________________________ + /** + * List of secure properties with more details, like value, location, and type + * + * @param opts The user and global flags that specify one of the four + * config files (aka layers). + * @returns Array of secure property details + */ + public secureFieldsWithDetails(opts?: { user: boolean; global: boolean }): IProfArgAttrs[] { + const config = this.getTeamConfig(); + const layer = opts ? config.findLayer(opts.user, opts.global) : config.layerActive(); + const fields = config.api.secure.findSecure(layer.properties.profiles, "profiles"); + const vault = config.api.secure.securePropsForLayer(layer.path); + + const response: IProfArgAttrs[] = []; + + // Search the vault for each secure field + if (vault) { + fields.forEach(fieldPath => { + // Search inside the secure fields for this layer + Object.entries(vault).map(([propPath, propValue]) => { + if (propPath === fieldPath) { + const dataType = ConfigSchema.findPropertyType(fieldPath, layer.properties, this.buildSchema([], layer)) as IProfDataType; + + response.push({ + argName: fieldPath.split(".properties.")[1], + dataType: dataType ?? this.argDataType(typeof propValue), + argValue: propValue as IProfDataType, + argLoc: { + locType: ProfLocType.TEAM_CONFIG, + osLoc: [layer.path], + jsonLoc: fieldPath + }, + }); + } + }); + }); + } + + fields.forEach(fieldPath => { + if (response.find(details => details.argLoc.jsonLoc === fieldPath) == null) { + const dataType = ConfigSchema.findPropertyType(fieldPath, layer.properties, this.buildSchema([], layer)) as IProfDataType ?? null; + response.push({ + argName: fieldPath.split(".properties.")[1], + dataType, + argValue: undefined, + argLoc: { + locType: ProfLocType.TEAM_CONFIG, + osLoc: [layer.path], + jsonLoc: fieldPath + } + }); + } + }); + + return response; + } + + // _______________________________________________________________________ /** * Get all of the subprofiles in the configuration. @@ -1785,7 +1583,7 @@ export class ProfileInfo { // Drop segment from end of path if property not found segments.pop(); } - const jsonPath = (segments.length > 0) ? buildPath(segments, opts.propName) : undefined; + const jsonPath = segments.length > 0 ? buildPath(segments, opts.propName) : undefined; if (jsonPath == null) { throw new ProfInfoErr({ errorCode: ProfInfoErr.PROP_NOT_IN_PROFILE, @@ -1796,7 +1594,7 @@ export class ProfileInfo { const foundInSecureArray = secFields.indexOf(buildPath(segments, opts.propName)) >= 0; const _isPropInLayer = (properties: IConfig) => { return properties && (lodash.get(properties, jsonPath) !== undefined || - (foundInSecureArray && lodash.get(properties, jsonPath.split(`.properties.${opts.propName}`)[0]) !== undefined)); + foundInSecureArray && lodash.get(properties, jsonPath.split(`.properties.${opts.propName}`)[0]) !== undefined); }; let filePath: string; @@ -1819,29 +1617,6 @@ export class ProfileInfo { }, foundInSecureArray]; } - /** - * Given a profile name and type, compute the profile location object - * containing OS location. - * @param profileName Name of an old school profile (e.g., LPAR1) - * @param profileType Type of an old school profile (e.g., zosmf) - */ - private argOldProfileLoc(profileName: string, profileType: string): IProfLoc { - return { - locType: ProfLocType.OLD_PROFILE, - osLoc: [this.oldProfileFilePath(profileType, profileName)] - }; - } - - /** - * Given a profile name and type, return the OS location of the associated - * YAML file. - * @param profileName Name of an old school profile (e.g., LPAR1) - * @param profileType Type of an old school profile (e.g., zosmf) - */ - private oldProfileFilePath(profileType: string, profileName: string) { - return path.join(this.mOldSchoolProfileRootDir, profileType, profileName + AbstractProfileManager.PROFILE_EXTENSION); - } - /** * Load the cached schema object for a profile type. Returns null if * schema is not found in the cache. @@ -1850,24 +1625,20 @@ export class ProfileInfo { private loadSchema(profile: IProfAttrs): IProfileSchema | null { let schemaMapKey: string; - if (profile.profLoc.locType === ProfLocType.TEAM_CONFIG) { - if (profile.profLoc.osLoc != null) { - // the profile exists, so use schema associated with its config JSON file - schemaMapKey = `${profile.profLoc.osLoc[0]}:${profile.profType}`; - } else { - // no profile exists, so loop through layers and use the first schema found - for (const layer of this.mLoadedConfig.mLayers) { - const tempKey = `${layer.path}:${profile.profType}`; - if (this.mProfileSchemaCache.has(tempKey)) { - schemaMapKey = tempKey; - break; - } + if (profile.profLoc.osLoc != null) { + // the profile exists, so use schema associated with its config JSON file + schemaMapKey = `${profile.profLoc.osLoc[0]}:${profile.profType}`; + } else { + // no profile exists, so loop through layers and use the first schema found + for (const layer of this.mLoadedConfig.mLayers) { + const tempKey = `${layer.path}:${profile.profType}`; + if (this.mProfileSchemaCache.has(tempKey)) { + schemaMapKey = tempKey; + break; } } - } else if (profile.profLoc.locType === ProfLocType.OLD_PROFILE) { - // for old school profiles, there is only one schema per profile type - schemaMapKey = profile.profType; } + if (schemaMapKey != null && this.mProfileSchemaCache.has(schemaMapKey)) { return this.mProfileSchemaCache.get(schemaMapKey); } @@ -1878,7 +1649,7 @@ export class ProfileInfo { // _______________________________________________________________________ /** * Override values in a merged argument object with values found in - * environment variables. The choice to override enviroment variables is + * environment variables. The choice to override environment variables is * controlled by an option on the ProfileInfo constructor. * * @param mergedArgs @@ -1892,8 +1663,10 @@ export class ProfileInfo { private overrideWithEnv(mergedArgs: IProfMergedArg, profSchema?: IProfileSchema) { if (!this.mOverrideWithEnv) return; // Don't do anything + const envPrefix = this.mAppName.toUpperCase(); + // Do we expect to always read "ZOWE_OPT_" environmental variables or "APPNAME_OPT_"? + // Populate any missing options - const envPrefix = ImperativeConfig.instance.loadedConfig.envVariablePrefix; const envStart = envPrefix + "_OPT_"; for (const key in process.env) { if (key.startsWith(envStart)) { @@ -1914,7 +1687,7 @@ export class ProfileInfo { if (profSchema == null || !argNameFound) { if (argValue.toUpperCase() === "TRUE" || argValue.toUpperCase() === "FALSE") { dataType = "boolean"; - } else if (!isNaN(+(argValue))) { + } else if (!isNaN(+argValue)) { dataType = "number"; } // TODO: Look for option definition for argName to check if it's an array @@ -1923,7 +1696,7 @@ export class ProfileInfo { if (dataType === "boolean") { argValue = argValue.toUpperCase() === "TRUE"; } else if (dataType === "number") { - argValue = +(argValue); + argValue = +argValue; } else if (dataType === "array") { argValue = CliUtils.extractArrayFromEnvValue(argValue); } diff --git a/packages/imperative/src/config/src/api/ConfigLayers.ts b/packages/imperative/src/config/src/api/ConfigLayers.ts index 3e90e8337c..e790c321ce 100644 --- a/packages/imperative/src/config/src/api/ConfigLayers.ts +++ b/packages/imperative/src/config/src/api/ConfigLayers.ts @@ -45,7 +45,8 @@ export class ConfigLayers extends ConfigApi { }); } try { - layer.properties = JSONC.parse(fileContents.toString()); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + layer.properties = JSONC.parse(fileContents.toString()) as any; layer.exists = true; } catch (e) { throw new ImperativeError({ @@ -78,7 +79,8 @@ export class ConfigLayers extends ConfigApi { // If fields are marked as secure const layer = opts ? this.mConfig.findLayer(opts.user, opts.global) : this.mConfig.layerActive(); - const layerCloned = JSONC.parse(JSONC.stringify(layer, null, ConfigConstants.INDENT)); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + const layerCloned = JSONC.parse(JSONC.stringify(layer, null, ConfigConstants.INDENT)) as any; this.mConfig.api.secure.cacheAndPrune(layerCloned); // Write the layer @@ -123,7 +125,8 @@ export class ConfigLayers extends ConfigApi { public get(): IConfigLayer { // Note: Add indentation to allow comments to be accessed via config.api.layers.get(), otherwise use layerActive() // return JSONC.parse(JSONC.stringify(this.mConfig.layerActive(), null, ConfigConstants.INDENT)); - return JSONC.parse(JSONC.stringify(this.mConfig.layerActive(), null, ConfigConstants.INDENT)); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + return JSONC.parse(JSONC.stringify(this.mConfig.layerActive(), null, ConfigConstants.INDENT)) as any; } // _______________________________________________________________________ @@ -155,14 +158,16 @@ export class ConfigLayers extends ConfigApi { public merge(cnfg: IConfig, dryRun: boolean = false): void | IConfigLayer { let layer: IConfigLayer; if (dryRun) { - layer = JSONC.parse(JSONC.stringify(this.mConfig.layerActive(), null, ConfigConstants.INDENT)); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + layer = JSONC.parse(JSONC.stringify(this.mConfig.layerActive(), null, ConfigConstants.INDENT)) as any; } else { layer = this.mConfig.layerActive(); } layer.properties.profiles = lodash.mergeWith(cnfg.profiles, layer.properties.profiles, (obj, src) => { if (lodash.isArray(obj) && lodash.isArray(src)) { - const temp = JSONC.parse(JSONC.stringify(obj, null, ConfigConstants.INDENT)); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + const temp = JSONC.parse(JSONC.stringify(obj, null, ConfigConstants.INDENT)) as any; src.forEach((val, idx) => { if (!temp.includes(val)) { temp.splice(idx, 0, val); @@ -174,7 +179,7 @@ export class ConfigLayers extends ConfigApi { layer.properties.defaults = lodash.merge(cnfg.defaults, layer.properties.defaults); - for (const pluginName of (cnfg.plugins || [])) { + for (const pluginName of cnfg.plugins || []) { if (layer.properties.plugins == null) { layer.properties.plugins = [pluginName]; } else if (!layer.properties.plugins?.includes(pluginName)) { diff --git a/packages/imperative/src/config/src/api/ConfigProfiles.ts b/packages/imperative/src/config/src/api/ConfigProfiles.ts index 3ccaadcef2..e80627bdfc 100644 --- a/packages/imperative/src/config/src/api/ConfigProfiles.ts +++ b/packages/imperative/src/config/src/api/ConfigProfiles.ts @@ -55,7 +55,8 @@ export class ConfigProfiles extends ConfigApi { public get(path: string, mustExist?: boolean): { [key: string]: string } { if (mustExist !== false && !this.exists(path)) return null; - return JSONC.parse(JSONC.stringify(this.buildProfile(path, this.mConfig.mProperties.profiles), null, ConfigConstants.INDENT)); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + return JSONC.parse(JSONC.stringify(this.buildProfile(path, this.mConfig.mProperties.profiles), null, ConfigConstants.INDENT)) as any; } // _______________________________________________________________________ @@ -67,7 +68,7 @@ export class ConfigProfiles extends ConfigApi { * @returns True if a profile exists. False otherwise. */ public exists(path: string): boolean { - return (this.findProfile(path, this.mConfig.mProperties.profiles) != null); + return this.findProfile(path, this.mConfig.mProperties.profiles) != null; } // _______________________________________________________________________ @@ -97,20 +98,6 @@ export class ConfigProfiles extends ConfigApi { return dflt != null ? this.get(dflt) : null; } - // _______________________________________________________________________ - /** - * Expands a short path into an expanded path. - * - * @param shortPath The short path. - * - * @returns The expanded path. - * - * @deprecated Please use getProfilePathFromName - */ - public expandPath(shortPath: string): string { - return this.getProfilePathFromName(shortPath); - } - // _______________________________________________________________________ /** * Expands a short path into an expanded path. diff --git a/packages/imperative/src/config/src/api/ConfigSecure.ts b/packages/imperative/src/config/src/api/ConfigSecure.ts index 625fed7f97..2333bfdd2e 100644 --- a/packages/imperative/src/config/src/api/ConfigSecure.ts +++ b/packages/imperative/src/config/src/api/ConfigSecure.ts @@ -20,6 +20,8 @@ import { ConfigConstants } from "../ConfigConstants"; import { IConfigProfile } from "../doc/IConfigProfile"; import { CredentialManagerFactory } from "../../../security"; import { ConfigUtils } from "../ConfigUtils"; +import { ZoweUserEvents } from "../../../events/src/EventConstants"; +import { EventOperator } from "../../../events/src/EventOperator"; /** * API Class for manipulating config layers. @@ -45,7 +47,8 @@ export class ConfigSecure extends ConfigApi { try { const s: string = await this.mConfig.mVault.load(ConfigConstants.SECURE_ACCT); if (s == null) return; - this.mConfig.mSecure = JSONC.parse(s); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + this.mConfig.mSecure = JSONC.parse(s) as any; } catch (error) { this.mLoadFailed = true; throw error; @@ -111,7 +114,7 @@ export class ConfigSecure extends ConfigApi { // Build the entries for each layer for (const { user, global } of this.mConfig.mLayers) { - if (allLayers || (user === this.mConfig.mActive.user && global === this.mConfig.mActive.global)) { + if (allLayers || user === this.mConfig.mActive.user && global === this.mConfig.mActive.global) { this.cacheAndPrune({ user, global }); } } @@ -129,6 +132,7 @@ export class ConfigSecure extends ConfigApi { */ public async directSave() { await this.mConfig.mVault.save(ConfigConstants.SECURE_ACCT, JSONC.stringify(this.mConfig.mSecure)); + EventOperator.getZoweProcessor().emitZoweEvent(ZoweUserEvents.ON_VAULT_CHANGED); } // _______________________________________________________________________ @@ -228,7 +232,7 @@ export class ConfigSecure extends ConfigApi { public findSecure(profiles: { [key: string]: IConfigProfile }, path: string): string[] { const secureProps = []; for (const profName of Object.keys(profiles)) { - for (const propName of (profiles[profName].secure || [])) { + for (const propName of profiles[profName].secure || []) { secureProps.push(`${path}.${profName}.properties.${propName}`); } if (profiles[profName].profiles != null) { @@ -238,6 +242,17 @@ export class ConfigSecure extends ConfigApi { return secureProps; } + /** + * Retrieve secure properties for a given layer path + * + * @param layerPath Path of the layer to get secure properties for + * @returns the secure properties for the given layer, or null if not found + */ + public securePropsForLayer(layerPath: string): IConfigSecureProperties { + const secureLayer = Object.keys(this.mConfig.mSecure).find(osLocation => osLocation === layerPath); + return secureLayer ? this.mConfig.mSecure[secureLayer] : null; + } + /** * Retrieve info that can be used to store a profile property securely. * @@ -295,6 +310,6 @@ export class ConfigSecure extends ConfigApi { * it was never called because the CredentialManager failed to initialize. */ public get loadFailed(): boolean { - return (this.mLoadFailed != null) ? this.mLoadFailed : !CredentialManagerFactory.initialized; + return this.mLoadFailed != null ? this.mLoadFailed : !CredentialManagerFactory.initialized; } } diff --git a/packages/imperative/src/config/src/doc/IConvertV1Profiles.ts b/packages/imperative/src/config/src/doc/IConvertV1Profiles.ts new file mode 100644 index 0000000000..2c463df139 --- /dev/null +++ b/packages/imperative/src/config/src/doc/IConvertV1Profiles.ts @@ -0,0 +1,97 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ProfileInfo } from "../ProfileInfo"; + +/** + * This is the structure of the input options to be supplied to ConvertV1Profiles.convert. + */ +export interface IConvertV1ProfOpts { + // Should V1 profiles be deleted after conversion? + deleteV1Profs: boolean; + + // The ProfileInfo object that the API will use to initialize the Secure Credential Manager. + // This property should be supplied by a VSCode application. + profileInfo?: ProfileInfo +} + +/** + * Message formatting constants. They can be ORed into IConvertMsg.msgFormat. + * Do not combine REPORT_LINE and ERROR_LINE. + */ +export enum ConvertMsgFmt { + REPORT_LINE = 0b00001, + ERROR_LINE = 0b00010, + PARAGRAPH = 0b00100, + INDENT = 0b01000 +} + +/** + * This is the structure of a conversion message. + */ +export class ConvertMsg { + public msgFormat: number; // Formatting options. A combination of ConvertMsgFmt values. + public msgText: string; // Message text with no formatting. + + public constructor(msgFormat: number, msgText: string) { + this.msgFormat = msgFormat; + this.msgText = msgText; + } +} + +/** + * This is the structure of the result from ConvertV1Profiles.convert. + */ +export interface IConvertV1ProfResult { + /** + * A report of actions and any error messages are contained in msgs. + * Each entry contains one line of text. No formatting or newlines are embedded. + * The caller is free to format the result as desired, using the msgType as a guide. + */ + msgs: ConvertMsg[]; + + /** + * If the old V1 Secure Credential Store plugin is currently installed, its + * name is returned in this property. The old SCS plugin will not be used, + * but the customer should probably uninstall it. Our caller can automatically + * uninstall that SCS plugin, or if our caller is unable to do so, our + * caller could inform the user that the plugin should be uninstalled. + * + * If the V1 SCS plugin is not installed, the property value will be null. + */ + v1ScsPluginName: string | null; + + /** + * This property indicates whether secure credentials were migrated during conversion. + * + * If the old V1 Secure Credential Store plugin was supplying the credential manager + * override and the CredentialManager was initialized before calling this function, + * profile conversion will not be able to migrate credentials from the old SCS plugin + * to the current embedded Secure Credential Store. + */ + credsWereMigrated: boolean; + + /** + * The following properties contain information about the success or failure of + * the conversion of V1 profiles. By displaying the values in the 'msgs' property, + * the caller need not use the following properties. However, our caller could + * decide to take special action or display custom messages, using the following + * properties. + */ + cfgFilePathNm: string; // existing or newly-created Zowe client config file name + numProfilesFound: number; + profilesConverted: { [key: string]: string[] }; + profilesFailed: { + name?: string; + type: string; + error: Error; + }[]; +} diff --git a/packages/imperative/src/config/src/doc/IProfOpts.ts b/packages/imperative/src/config/src/doc/IProfOpts.ts index 8bc78f16cd..ca5b5f14bb 100644 --- a/packages/imperative/src/config/src/doc/IProfOpts.ts +++ b/packages/imperative/src/config/src/doc/IProfOpts.ts @@ -28,14 +28,6 @@ export interface IProfOpts { */ overrideWithEnv?: boolean; - /** - * Implements a custom method to require Keytar module which manages - * secure credentials. If undefined, the default implementation is to - * `require("keytar")` from the caller app's node_modules folder. - * @deprecated - */ - requireKeytar?: () => NodeModule; - /** * Overrides the credential manager class used to load and store secure * properties. If undefined, the default implementation is to use the diff --git a/packages/imperative/src/error/src/doc/IImperativeErrorParms.ts b/packages/imperative/src/error/src/doc/IImperativeErrorParms.ts index 50b817efd3..f7fbb939a4 100644 --- a/packages/imperative/src/error/src/doc/IImperativeErrorParms.ts +++ b/packages/imperative/src/error/src/doc/IImperativeErrorParms.ts @@ -25,7 +25,8 @@ export interface IImperativeErrorParms { logger?: Logger; /** * Message tag - prepended to the error message specified. Useful for categorizing error messages - * (e.g. "Profile IO Error"). A ": " is appended automatically (e.g. "Profile IO Error: ") + * (e.g. "V1ProfileRead Read Error"). + * A ": " is appended automatically (e.g. "V1ProfileRead Read Error: ") * @type {string} * @memberof IImperativeErrorParms */ diff --git a/packages/imperative/src/events/__tests__/__integration__/EventOperator_and_Processor.integration.test.ts b/packages/imperative/src/events/__tests__/__integration__/EventOperator_and_Processor.integration.test.ts new file mode 100644 index 0000000000..12c1741456 --- /dev/null +++ b/packages/imperative/src/events/__tests__/__integration__/EventOperator_and_Processor.integration.test.ts @@ -0,0 +1,178 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { SetupTestEnvironment } from "../../../../__tests__/__src__/environment/SetupTestEnvironment"; +import { ConfigUtils, EventCallback, EventOperator, EventProcessor, EventUtils, IEventJson, ZoweSharedEvents } from "../../.."; +import * as fs from "fs"; +import * as path from "path"; +import { IExtendersJsonOpts } from "../../../config/src/doc/IExtenderOpts"; + +const zoweApp = "Zowe"; +const sampleApps = ["firstApp", "secondApp"]; +let zoweCliHome: string; + +/** + * ## Understanding Event Files + * | Zowe Event Dir | <...>/.zowe/.events/Zowe/ + * | Custom Event Dir | <...>/.zowe/.events/custApp/ + * + * ## Understanding Event Types + * - **Shared Events**: Zowe events that when triggered, notify all subscribed users. + * - **User Events**: Zowe events that are specific to a particular user or session. + * - **Custom Events**: Applications can define their own shared and user events. +*/ +describe("Event Operator and Processor", () => { + const sharedZoweEvent = ZoweSharedEvents.ON_CREDENTIAL_MANAGER_CHANGED; + const customUserEvent = "onCustomUserEvent"; + beforeAll(async () => { + await SetupTestEnvironment.createTestEnv({ + cliHomeEnvVar: "ZOWE_CLI_HOME", + testName: "event_operator_and_processor" + }); + // have to reset because test environment doesn't add .zowe to ZOWE_CLI_HOME :( + process.env.ZOWE_CLI_HOME = path.join(process.env.ZOWE_CLI_HOME || '', ".zowe"); + zoweCliHome = process.env.ZOWE_CLI_HOME; + EventUtils.ensureEventsDirExists(zoweCliHome); + const extJson: IExtendersJsonOpts = ConfigUtils.readExtendersJson(); + sampleApps.forEach(app => extJson.profileTypes[app] = { from: [app] }); + ConfigUtils.writeExtendersJson(extJson); + }); + + beforeEach(() => { + jest.restoreAllMocks(); + }); + + describe("Zowe Events", () => { + it("should create an event file upon first subscription if file does not exist", async () => { + const setupWatcherSpy = jest.spyOn(EventUtils, "setupWatcher"); + const callback = jest.fn(); + const Watcher = EventOperator.getWatcher(zoweApp); + const Emitter = EventOperator.getZoweProcessor(); + + expect((Watcher as EventProcessor).subscribedEvents.get(sharedZoweEvent)).toBeFalsy(); + + // Subscribe to event + Watcher.subscribeShared(sharedZoweEvent, callback); + const eventDetails: IEventJson = (Watcher as any).subscribedEvents.get(sharedZoweEvent).toJson(); + + expect(callback).not.toHaveBeenCalled(); + expect(fs.existsSync(eventDetails.eventFilePath)).toBeTruthy(); + + // Emit event and trigger callback + Emitter.emitZoweEvent(sharedZoweEvent); + setupWatcherSpy.mock.calls.forEach(call => (call[2] as Function)()); // Mock event emission + + expect(eventDetails.eventName).toEqual(sharedZoweEvent); + expect(EventUtils.isSharedEvent(eventDetails.eventName)).toBeTruthy(); + expect(callback).toHaveBeenCalled(); + EventOperator.deleteProcessor(zoweApp); + }); + + it("should trigger subscriptions for all instances watching for ZoweSharedEvent", async () => { + const setupWatcherSpy = jest.spyOn(EventUtils, "setupWatcher"); + // create two watchers watching the same app (Zowe - default) + const firstWatcher = EventOperator.getWatcher(); + const secondWatcher = EventOperator.getWatcher(); + const Emitter = EventOperator.getZoweProcessor(); + + const firstCallback: EventCallback = jest.fn() as EventCallback; + const secondCallback: EventCallback = jest.fn() as EventCallback; + + // We expect no subscriptions yet + expect((firstWatcher as EventProcessor).subscribedEvents.get(sharedZoweEvent)).toBeFalsy(); + expect((secondWatcher as EventProcessor).subscribedEvents.get(sharedZoweEvent)).toBeFalsy(); + + // Subscribe to event + firstWatcher.subscribeShared(sharedZoweEvent, firstCallback); + secondWatcher.subscribeShared(sharedZoweEvent, secondCallback); + const firstEventDetails: IEventJson = (firstWatcher as any).subscribedEvents.get(sharedZoweEvent).toJson(); + const secondEventDetails: IEventJson = (secondWatcher as any).subscribedEvents.get(sharedZoweEvent).toJson(); + + // Emit event and trigger callbacks + Emitter.emitZoweEvent(sharedZoweEvent); + setupWatcherSpy.mock.calls.forEach(call => (call[2] as Function)()); + + expect(firstEventDetails.eventName).toEqual(sharedZoweEvent); + expect(secondEventDetails.eventName).toEqual(sharedZoweEvent); + expect(EventUtils.isSharedEvent(firstEventDetails.eventName)).toBeTruthy(); + expect(EventUtils.isSharedEvent(secondEventDetails.eventName)).toBeTruthy(); + expect(firstCallback).toHaveBeenCalled(); + expect(secondCallback).toHaveBeenCalled(); + EventOperator.deleteProcessor(zoweApp); + }); + + it("should not affect subscriptions from another instance when unsubscribing from events", async () => { + const setupWatcherSpy = jest.spyOn(EventUtils, "setupWatcher"); + // create two watchers watching the same app (Zowe) + // BUT because we are in the same process and can't actually simulate different processes, + // need to fake out unsubscription of secondWatcher by watching for the same event on another app + const firstWatcher = EventOperator.getWatcher(); + const secondWatcher = EventOperator.getWatcher(sampleApps[0]); + const Emitter = EventOperator.getZoweProcessor(); + + const firstCallback: EventCallback = jest.fn() as EventCallback; + const secondCallback: EventCallback = jest.fn() as EventCallback; + + expect((firstWatcher as EventProcessor).subscribedEvents.get(sharedZoweEvent)).toBeFalsy(); + expect((secondWatcher as EventProcessor).subscribedEvents.get(sharedZoweEvent)).toBeFalsy(); + + // Subscribe to event + firstWatcher.subscribeShared(sharedZoweEvent, firstCallback); + secondWatcher.subscribeShared(sharedZoweEvent, secondCallback); + + // unsubscribe! + secondWatcher.unsubscribe(sharedZoweEvent); + + expect((firstWatcher as any).subscribedEvents.get(sharedZoweEvent)).toBeTruthy(); + expect((secondWatcher as any).subscribedEvents.get(sharedZoweEvent)).toBeFalsy(); + + // Emit event and trigger callbacks + Emitter.emitZoweEvent(sharedZoweEvent); + setupWatcherSpy.mock.calls.forEach(call => { + if (call[0].appName === zoweApp) { (call[2] as Function)(); } + }); + + expect(firstCallback).toHaveBeenCalled(); + expect(secondCallback).not.toHaveBeenCalled(); + EventOperator.deleteProcessor(sampleApps[0]); + EventOperator.deleteProcessor(zoweApp); + }); + }); + + describe("Custom Events", () => { + it("should create an event file upon first subscription if file does not exist - specific to CustomUserEvent directory structure", + async () => { + const setupWatcherSpy = jest.spyOn(EventUtils, "setupWatcher"); + const callback = jest.fn(); + const Watcher = EventOperator.getWatcher(sampleApps[1]); + const Emitter = EventOperator.getEmitter(sampleApps[1]); + const eventDir = path.join(zoweCliHome, ".events", sampleApps[1]); //corresponds to emitter's event file + + expect((Watcher as EventProcessor).subscribedEvents.get(customUserEvent)).toBeFalsy(); + + // Subscribe to event + Watcher.subscribeUser(customUserEvent, callback); + const eventDetails: IEventJson = (Watcher as any).subscribedEvents.get(customUserEvent).toJson(); + expect(callback).not.toHaveBeenCalled(); + expect(fs.existsSync(eventDetails.eventFilePath)).toBeTruthy(); + + // Emit event and trigger callback + Emitter.emitEvent(customUserEvent); + setupWatcherSpy.mock.calls.forEach(call => (call[2] as Function)()); + + expect(eventDetails.eventName).toEqual(customUserEvent); + expect(eventDetails.eventFilePath).toContain(eventDir); + expect(callback).toHaveBeenCalled(); + expect(EventUtils.isUserEvent(eventDetails.eventName)).toBeFalsy(); //ensuring this custom event isnt a Zowe event + EventOperator.deleteProcessor(sampleApps[1]); + }); + }); +}); diff --git a/packages/imperative/src/events/__tests__/__unit__/EventOperator.unit.test.ts b/packages/imperative/src/events/__tests__/__unit__/EventOperator.unit.test.ts new file mode 100644 index 0000000000..87063402ee --- /dev/null +++ b/packages/imperative/src/events/__tests__/__unit__/EventOperator.unit.test.ts @@ -0,0 +1,165 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { EventOperator } from '../../src/EventOperator'; +import { EventProcessor } from '../../src/EventProcessor'; +import { EventUtils, Logger } from '../../..'; +import { IProcessorTypes } from '../../src/doc'; +import { Event } from '../../..'; +import { EventTypes, ZoweUserEvents } from "../../src/EventConstants"; + +jest.mock('../../../logger'); +jest.mock('../../src/EventProcessor'); +jest.mock('../../src/Event'); + +const logger = Logger.getImperativeLogger(); +const appName = 'TestApp'; + +describe("EventOperator Unit Tests", () => { + beforeEach(() => { + jest.clearAllMocks(); + jest.spyOn(EventUtils, "getListOfApps").mockReturnValue(["Zowe", appName]); + const subs = EventProcessor.prototype.subscribedEvents = new Map(); + const dummyEvent: any = { subscriptions: [ { removeAllListeners: jest.fn().mockReturnValue({close: jest.fn()})} as any] } ; + subs.set("Zowe", dummyEvent); + }); + afterEach(() => { + EventOperator.deleteProcessor("Zowe"); + EventOperator.deleteProcessor(appName); + }); + afterAll(() => { + jest.restoreAllMocks(); + }); + + describe("processor tests", () => { + it("'createProcessor' should create a new 'EventProcessor' if not already existing", () => { + const type = IProcessorTypes.BOTH; + const processor = EventOperator.getProcessor(appName, logger); + + expect(EventProcessor).toHaveBeenCalledWith(appName, type, logger); + expect(processor).toBeInstanceOf(EventProcessor); + }); + + it("'getZoweProcessor' should return the Zowe processor instance", () => { + const processor = EventOperator.getZoweProcessor(); + + expect(EventProcessor).toHaveBeenCalledWith("Zowe", IProcessorTypes.BOTH, logger); + expect(processor).toBeInstanceOf(EventProcessor); + }); + + it('emitZoweEvent is called by a Zowe processor and emits a ZoweUserEvents', () => { + const processor = EventOperator.getZoweProcessor(); + const eventName = "onVaultChanged"; + const emitZoweEventSpy = jest.spyOn(processor, 'emitZoweEvent'); + + processor.emitZoweEvent(eventName); + + expect(emitZoweEventSpy).toHaveBeenCalledWith(eventName); + expect(Object.values(ZoweUserEvents)).toContain(eventName); + }); + + it("'getProcessor' should return a generic event processor", () => { + const processor = EventOperator.getProcessor(appName, logger); + + expect(EventProcessor).toHaveBeenCalledWith(appName, IProcessorTypes.BOTH, logger); + expect(processor).toBeInstanceOf(EventProcessor); + }); + + it("'deleteProcessor' should remove the correct event processor", () => { + const processor = new EventProcessor(appName, IProcessorTypes.BOTH); + processor.subscribedEvents = new Map([ + ['testEvent', { + eventTime: '', + eventName: 'testEvent', + eventType: EventTypes.SharedEvents, + appName: appName, + subscriptions: new Set([ + { + removeAllListeners: jest.fn(), + close: jest.fn() + } + ]) + } as unknown as Event] + ]); + + EventOperator.deleteProcessor(appName); + + expect(EventOperator['instances'].has(appName)).toBe(false); + }); + }); + + describe("watcher tests", () => { + it("'getWatcher' should return a Zowe watcher as the default", () => { + const processor = EventOperator.getWatcher(); + + expect(EventProcessor).toHaveBeenCalledWith("Zowe", IProcessorTypes.WATCHER, undefined); + expect(processor).toBeInstanceOf(EventProcessor); + }); + it("'getWatcher' should return a watcher-only event processor", () => { + const processor = EventOperator.getWatcher(appName, logger); + + expect(EventProcessor).toHaveBeenCalledWith(appName, IProcessorTypes.WATCHER, logger); + expect(processor).toBeInstanceOf(EventProcessor); + }); + it("'deleteWatcher' should remove the correct event processor", () => { + const processor = new EventProcessor(appName, IProcessorTypes.WATCHER); + processor.subscribedEvents = new Map([ + ['testEvent', { + eventTime: '', + eventName: 'testEvent', + eventType: EventTypes.UserEvents, + appName: appName, + subscriptions: new Set([ + { + removeAllListeners: jest.fn(), + close: jest.fn() + } + ]) + } as unknown as Event] + ]); + + EventOperator.deleteWatcher(appName); + + expect(EventOperator['instances'].has(appName)).toBe(false); + }); + }); + + describe("emitter tests", () => { + it("'getEmitter' should return an emitter-only event processor", () => { + const processor = EventOperator.getEmitter(appName, logger); + + expect(EventProcessor).toHaveBeenCalledWith(appName, IProcessorTypes.EMITTER, logger); + expect(processor).toBeInstanceOf(EventProcessor); + }); + + it("'deleteEmitter' should remove the correct event processor", () => { + const processor = new EventProcessor(appName, IProcessorTypes.EMITTER); + processor.subscribedEvents = new Map([ + ['testEvent', { + eventTime: '', + eventName: 'testEvent', + eventType: EventTypes.UserEvents, + appName: appName, + subscriptions: new Set([ + { + removeAllListeners: jest.fn(), + close: jest.fn() + } + ]) + } as unknown as Event] + ]); + + EventOperator.deleteEmitter(appName); + + expect(EventOperator['instances'].has(appName)).toBe(false); + }); + }); +}); \ No newline at end of file diff --git a/packages/imperative/src/events/__tests__/__unit__/EventProcessor.unit.test.ts b/packages/imperative/src/events/__tests__/__unit__/EventProcessor.unit.test.ts new file mode 100644 index 0000000000..e98756b116 --- /dev/null +++ b/packages/imperative/src/events/__tests__/__unit__/EventProcessor.unit.test.ts @@ -0,0 +1,182 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { EventProcessor } from '../../src/EventProcessor'; +import { EventUtils } from '../../src/EventUtils'; +import { IProcessorTypes } from '../../src/doc/IEventInstanceTypes'; +import { ImperativeError } from '../../../error/src/ImperativeError'; +import { Event } from '../../src/Event'; +import { EventTypes, ZoweSharedEvents, ZoweUserEvents } from '../../src/EventConstants'; +import { EventOperator } from '../../src/EventOperator'; + +jest.mock('../../../logger/src/Logger'); + +describe('EventProcessor Unit Tests', () => { + let createSubscriptionSpy: any; + let setupWatcherSpy: any; + const appName = 'TestApp'; + + beforeEach(() => { + jest.clearAllMocks(); + jest.spyOn(EventUtils, 'writeEvent').mockImplementation(jest.fn()); + createSubscriptionSpy = jest.spyOn(EventUtils, 'createSubscription').mockImplementation(jest.fn()); + setupWatcherSpy = jest.spyOn(EventUtils, 'setupWatcher').mockImplementation(jest.fn()); + + jest.spyOn(EventUtils, "getListOfApps").mockReturnValue(["Zowe", appName]); + const subs = EventProcessor.prototype.subscribedEvents = new Map(); + const dummyEvent: any = { subscriptions: [ { removeAllListeners: jest.fn().mockReturnValue({close: jest.fn()})} as any] } ; + subs.set("Zowe", dummyEvent); + }); + afterEach(() => { + EventOperator.deleteProcessor(appName); + }); + afterAll(() => { + jest.restoreAllMocks(); + }); + + describe('Constructor', () => { + it('initializes EventProcessor correctly', () => { + expect(EventOperator['instances'].get(appName)).toBeUndefined(); + + EventOperator.getProcessor(appName); + + expect(EventOperator['instances'].get(appName)).toBeDefined(); + }); + }); + + describe('Subscription Methods', () => { + it('"subscribeShared" throws error for emitter-only processor', () => { + const emitter = new EventProcessor(appName, IProcessorTypes.EMITTER); + expect(() => emitter.subscribeShared('fakeEventToSubscribeTo', () => {})).toThrow(ImperativeError); + }); + + it('"subscribeUser" throws error for emitter-only processor', () => { + const emitter = new EventProcessor(appName, IProcessorTypes.EMITTER); + expect(() => emitter.subscribeUser('fakeEventToSubscribeTo', () => {})).toThrow(ImperativeError); + }); + + it('"subscribeShared" correctly subscribes to shared events', () => { + const processor = new EventProcessor(appName, IProcessorTypes.BOTH); + const eventName = 'someEvent'; + const callbacks = [jest.fn()]; + + createSubscriptionSpy.mockReturnValue({ close: jest.fn() }); + + const disposable = processor.subscribeShared(eventName, callbacks); + + expect(createSubscriptionSpy).toHaveBeenCalledWith(processor, eventName, EventTypes.SharedEvents); + expect(setupWatcherSpy).toHaveBeenCalledWith(processor, eventName, callbacks); + expect(disposable).toBeDefined(); + }); + + it('"subscribeUser" correctly subscribes to user-specific events', () => { + const processor = new EventProcessor(appName, IProcessorTypes.BOTH); + const eventName = 'someEvent'; + const callbacks = [jest.fn()]; + + createSubscriptionSpy.mockReturnValue({ close: jest.fn() }); + + const disposable = processor.subscribeUser(eventName, callbacks); + + expect(createSubscriptionSpy).toHaveBeenCalledWith(processor, eventName, EventTypes.UserEvents); + expect(setupWatcherSpy).toHaveBeenCalledWith(processor, eventName, callbacks); + expect(disposable).toBeDefined(); + }); + }); + + describe('Emission Methods', () => { + it('"emitEvent" throws error for watcher-only processor', () => { + const watcher = new EventProcessor(appName, IProcessorTypes.WATCHER); + expect(() => watcher.emitEvent('someEvent')).toThrow(ImperativeError); + }); + + it('"emitEvent" throws error when emitting Zowe events', () => { + const emitter = new EventProcessor(appName, IProcessorTypes.EMITTER); + expect(() => emitter.emitEvent(ZoweUserEvents.ON_VAULT_CHANGED)).toThrow(ImperativeError); + expect(() => emitter.emitEvent(ZoweSharedEvents.ON_CREDENTIAL_MANAGER_CHANGED)).toThrow(ImperativeError); + }); + + it('"emitZoweEvent" throws error for watcher-only processor', () => { + const watcher = new EventProcessor(appName, IProcessorTypes.WATCHER); + expect(() => watcher.emitZoweEvent('someEvent')).toThrow(ImperativeError); + }); + + it('"emitZoweEvent" throws error when emitting non Zowe events', () => { + const emitter = EventOperator.getZoweProcessor(); + expect(() => emitter.emitZoweEvent('someEvent')).toThrow(ImperativeError); + }); + + it('"emitEvent" updates event timestamp and writes event', () => { + const emitter = new EventProcessor(appName, IProcessorTypes.EMITTER); + const eventName = 'someEvent'; + const event = { eventTime: '', eventName, eventType: EventTypes.UserEvents, appName, subscriptions: new Set() } as unknown as Event; + + emitter.subscribedEvents.set(eventName, event); + emitter.emitEvent(eventName); + + expect(event.eventTime).not.toBe(''); + expect(EventUtils.writeEvent).toHaveBeenCalledWith(event); + }); + }); + + describe('Unsubscribe Methods', () => { + it('"unsubscribe" removes subscriptions and cleans up resources', () => { + const processor = new EventProcessor(appName, IProcessorTypes.BOTH); + processor.subscribedEvents = new Map([ + ['testEvent', { + eventTime: '', + eventName: 'testEvent', + eventType: EventTypes.UserEvents, + appName: appName, + subscriptions: new Set([ + { + removeAllListeners: jest.fn(), + close: jest.fn() + } + ]) + } as unknown as Event] + ]); + + processor.unsubscribe('testEvent'); + + expect(processor.subscribedEvents.has('testEvent')).toBe(false); + }); + it('subscription removed from a processor\'s subscribed events and resources are cleaned', () => { + const processor = new EventProcessor(appName, IProcessorTypes.BOTH); + const mockSubscription = { + removeAllListeners: jest.fn(), + close: jest.fn() + }; + + const event = { + eventTime: '', + eventName: 'testEvent', + eventType: EventTypes.UserEvents, + appName: appName, + subscriptions: new Set([mockSubscription]) + } as unknown as Event; + + processor.subscribedEvents = new Map([ + ['testEvent', event] + ]); + + expect(processor.subscribedEvents.has('testEvent')).toBe(true); + processor.unsubscribe('testEvent'); + expect(mockSubscription.removeAllListeners).toHaveBeenCalled(); + expect(mockSubscription.close).toHaveBeenCalled(); + expect(processor.subscribedEvents.has('testEvent')).toBe(false); + }); + it('"unsubscribe" throws error for emitter-only processor', () => { + const emitter = new EventProcessor(appName, IProcessorTypes.EMITTER); + expect(() => emitter.unsubscribe('someEvent')).toThrow(ImperativeError); + }); + }); +}); \ No newline at end of file diff --git a/packages/imperative/src/events/__tests__/__unit__/EventUtils.unit.test.ts b/packages/imperative/src/events/__tests__/__unit__/EventUtils.unit.test.ts new file mode 100644 index 0000000000..7967ecda59 --- /dev/null +++ b/packages/imperative/src/events/__tests__/__unit__/EventUtils.unit.test.ts @@ -0,0 +1,156 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { EventOperator } from '../../src/EventOperator'; +import { EventProcessor } from '../../src/EventProcessor'; +import { Logger } from '../../..'; +import { IProcessorTypes } from '../../src/doc'; +import { Event } from '../../..'; +import { EventTypes, ZoweUserEvents } from "../../src/EventConstants"; + +jest.mock('../../src/EventProcessor'); +jest.mock('../../../logger'); + +const logger = Logger.getImperativeLogger(); + +describe("EventOperator Unit Tests", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + afterAll(() => { + jest.restoreAllMocks(); + }); + + describe("processor tests", () => { + it("'createProcessor' should create a new 'EventProcessor' if not already existing", () => { + const appName = 'TestApp'; + const type = IProcessorTypes.BOTH; + const processor = EventOperator.getProcessor(appName, logger); + + expect(EventProcessor).toHaveBeenCalledWith(appName, type, logger); + expect(processor).toBeInstanceOf(EventProcessor); + }); + + it("'getZoweProcessor' should return the Zowe processor instance", () => { + const processor = EventOperator.getZoweProcessor(); + + expect(EventProcessor).toHaveBeenCalledWith("Zowe", IProcessorTypes.BOTH, logger); + expect(processor).toBeInstanceOf(EventProcessor); + }); + + it('emitZoweEvent is called by a Zowe processor and emits a ZoweUserEvents', () => { + const processor = EventOperator.getZoweProcessor(); + const eventName = "onVaultChanged"; + const emitZoweEventSpy = jest.spyOn(processor, 'emitZoweEvent'); + + processor.emitZoweEvent(eventName); + + expect(emitZoweEventSpy).toHaveBeenCalledWith(eventName); + expect(Object.values(ZoweUserEvents)).toContain(eventName); + }); + + it("'getProcessor' should return a generic event processor", () => { + const appName = 'GenericApp'; + const processor = EventOperator.getProcessor(appName, logger); + + expect(EventProcessor).toHaveBeenCalledWith(appName, IProcessorTypes.BOTH, logger); + expect(processor).toBeInstanceOf(EventProcessor); + }); + + it("'deleteProcessor' should remove the correct event processor", () => { + const appName = 'DeleteApp'; + const processor = new EventProcessor(appName, IProcessorTypes.BOTH); + processor.subscribedEvents = new Map([ + ['testEvent', { + eventTime: '', + eventName: 'testEvent', + eventType: EventTypes.SharedEvents, + appName: appName, + subscriptions: new Set([ + { + removeAllListeners: jest.fn(), + close: jest.fn() + } + ]) + } as unknown as Event] + ]); + + EventOperator.deleteProcessor(appName); + + expect(EventOperator['instances'].has(appName)).toBe(false); + }); + }); + + describe("watcher tests", () => { + it("'getWatcher' should return a watcher-only event processor", () => { + const appName = 'WatcherApp'; + const processor = EventOperator.getWatcher(appName, logger); + + expect(EventProcessor).toHaveBeenCalledWith(appName, IProcessorTypes.WATCHER, logger); + expect(processor).toBeInstanceOf(EventProcessor); + }); + it("'deleteWatcher' should remove the correct event processor", () => { + const appName = 'DeleteWatcher'; + const processor = new EventProcessor(appName, IProcessorTypes.WATCHER); + processor.subscribedEvents = new Map([ + ['testEvent', { + eventTime: '', + eventName: 'testEvent', + eventType: EventTypes.UserEvents, + appName: appName, + subscriptions: new Set([ + { + removeAllListeners: jest.fn(), + close: jest.fn() + } + ]) + } as unknown as Event] + ]); + + EventOperator.deleteWatcher(appName); + + expect(EventOperator['instances'].has(appName)).toBe(false); + }); + }); + + describe("emitter tests", () => { + it("'getEmitter' should return an emitter-only event processor", () => { + const appName = 'EmitterApp'; + const processor = EventOperator.getEmitter(appName, logger); + + expect(EventProcessor).toHaveBeenCalledWith(appName, IProcessorTypes.EMITTER, logger); + expect(processor).toBeInstanceOf(EventProcessor); + }); + + it("'deleteEmitter' should remove the correct event processor", () => { + const appName = 'DeleteEmitter'; + const processor = new EventProcessor(appName, IProcessorTypes.EMITTER); + processor.subscribedEvents = new Map([ + ['testEvent', { + eventTime: '', + eventName: 'testEvent', + eventType: EventTypes.UserEvents, + appName: appName, + subscriptions: new Set([ + { + removeAllListeners: jest.fn(), + close: jest.fn() + } + ]) + } as unknown as Event] + ]); + + EventOperator.deleteEmitter(appName); + + expect(EventOperator['instances'].has(appName)).toBe(false); + }); + }); +}); \ No newline at end of file diff --git a/packages/imperative/src/config/src/doc/IConfigConvertResult.ts b/packages/imperative/src/events/index.ts similarity index 55% rename from packages/imperative/src/config/src/doc/IConfigConvertResult.ts rename to packages/imperative/src/events/index.ts index 8661a06c9a..0c3a6c5326 100644 --- a/packages/imperative/src/config/src/doc/IConfigConvertResult.ts +++ b/packages/imperative/src/events/index.ts @@ -9,14 +9,9 @@ * */ -import { IConfig } from "./IConfig"; - -export interface IConfigConvertResult { - config: IConfig; - profilesConverted: { [key: string]: string[] }; - profilesFailed: { - name?: string; - type: string; - error: Error; - }[]; -} +export * from "./src/doc"; +export * from "./src/Event"; +export * from "./src/EventConstants"; +export * from "./src/EventProcessor"; +export * from "./src/EventOperator"; +export * from "./src/EventUtils"; \ No newline at end of file diff --git a/packages/imperative/src/events/src/Event.ts b/packages/imperative/src/events/src/Event.ts new file mode 100644 index 0000000000..d316e215c9 --- /dev/null +++ b/packages/imperative/src/events/src/Event.ts @@ -0,0 +1,66 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { FSWatcher } from "fs"; +import { EventTypes } from "./EventConstants"; +import { IEventJson } from "./doc"; + +/** + * Represents an event within the system, containing all necessary metadata + * and subscriptions related to the event. + */ +export class Event implements IEventJson { + public eventTime: string; + public eventName: string; + public eventType: EventTypes; + public appName: string; + public eventFilePath: string; + public subscriptions: FSWatcher[]; + + + /** + * Initializes a new instance of the Event class with specified properties. + * + * @param {IEventJson} params - The parameters to create the Event. + */ + constructor({ eventTime, eventName, eventType, appName, eventFilePath, subscriptions }: IEventJson) { + this.eventTime = eventTime; + this.eventName = eventName; + this.eventType = eventType ?? null; + this.appName = appName; + this.eventFilePath = eventFilePath; + this.subscriptions = subscriptions; + } + + /** + * Serializes the Event object to a JSON object for storage or transmission. + * + * @returns {Object} The JSON representation of the event. + */ + public toJson(): IEventJson { + return { + eventTime: this.eventTime, + eventName: this.eventName, + eventType: this.eventType, + appName: this.appName, + eventFilePath: this.eventFilePath, + }; + } + + /** + * Provides a string representation of the Event, useful for logging and debugging. + * + * @returns {string} A string detailing the event's significant information. + */ + public toString = (): string => { + return `Name: ${this.eventName} \t| Time: ${this.eventTime} \t| App: ${this.appName} \t| Type: ${this.eventType}`; + }; +} \ No newline at end of file diff --git a/packages/imperative/src/events/src/EventConstants.ts b/packages/imperative/src/events/src/EventConstants.ts new file mode 100644 index 0000000000..61641bdd20 --- /dev/null +++ b/packages/imperative/src/events/src/EventConstants.ts @@ -0,0 +1,53 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + + +export enum ZoweUserEvents { + ON_VAULT_CHANGED = "onVaultChanged" +} + +export enum ZoweSharedEvents { + ON_CREDENTIAL_MANAGER_CHANGED = "onCredentialManagerChanged" +} + +export enum EventTypes { ZoweUserEvents, ZoweSharedEvents, SharedEvents, UserEvents } + +export type EventCallback = () => void | PromiseLike; + +/** + * EXPECTED EVENT LOCATIONS: + * + * Shared events: + * Global: + * - $ZOWE_CLI_HOME/.events/onConfigChanged + * - $ZOWE_CLI_HOME/.events/onSchemaChanged + * Project: + * - $ZOWE_CLI_HOME/.events//onConfigChanged + * - $ZOWE_CLI_HOME/.events//onSchemaChanged + * + * User events: + * Global: + * - ~/.zowe/.events/onUserConfigChanged + * Project: + * - ~/.zowe/.events//onUserConfigChanged + * + * Custom events: + * Shared: + * Global: + * - $ZOWE_CLI_HOME/.events// + * Project: + * - $ZOWE_CLI_HOME/.events/// + * User: + * Global: + * - ~/.zowe/.events// + * Project: + * - ~/.zowe/.events/// + */ \ No newline at end of file diff --git a/packages/imperative/src/events/src/EventOperator.ts b/packages/imperative/src/events/src/EventOperator.ts new file mode 100644 index 0000000000..d2a69d6ce2 --- /dev/null +++ b/packages/imperative/src/events/src/EventOperator.ts @@ -0,0 +1,170 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { EventProcessor } from "./EventProcessor"; +import { IEmitter, IEmitterAndWatcher, IProcessorTypes, IWatcher } from "./doc/IEventInstanceTypes"; +import { Logger } from "../../logger"; + +/** + * @internal Interface for Zowe-specific event processing, combining emitter and watcher functionalities. + */ +interface IZoweProcessor extends IEmitterAndWatcher { + emitZoweEvent(eventName: string): void; +} + +/** + * ## Overview + * The `EventOperator` manages event processors and sets limits on their behavior. + * + * An `EventOperator` categorizes processors into 3 types: + * - **Watcher**: Listens for events and triggers callbacks when events occur. + * - **Emitter**: Emits events that other applications listen for. + * - **EmitterAndWatcher**: Combines the functionalities of both watcher and emitter. + * + * Applications use the `EventOperator` to obtain the appropriate event processor based on their needs. + * For example, an application might use a watcher to react to user actions and an emitter to notify other + * components of state changes. + * + * ### App Names and Processors + * Processors are tied to application names to prevent event collisions and to maintain a clear separation + * of event domains. Valid app names are defined in the list of extenders (formal plugin names or ZE extender names). + * + * ### Understanding Event Types + * - **Predefined Zowe Events**: Zowe provides a set of predefined shared and user events that can be watched. + * - **Custom Events**: Applications can define their own shared/user events, allowing for custom event-driven behavior. + * + * @export + * @class EventOperator + */ +export class EventOperator { + private static instances: Map = new Map(); + /** + * Creates an event processor for a specified application. + * + * @static + * @param {string} appName - The name of the application. + * @param {IProcessorTypes} type - The type of processor to create (emitter, watcher, or both). + * @param {Logger} [logger] - Optional logger instance for the processor. + * @returns {IZoweProcessor} A new or existing processor instance. + * @throws {ImperativeError} If the application name is not recognized. + */ + private static createProcessor(appName: string, type: IProcessorTypes, logger?: Logger): IZoweProcessor { + if (!this.instances.has(appName)) { + const newInstance = new EventProcessor(appName, type, logger); + this.instances.set(appName, newInstance); + } + const procInstance = this.instances.get(appName); + if (procInstance.processorType !== type) { + procInstance.processorType = IProcessorTypes.BOTH; + } + return procInstance; + } + /** + * Retrieves a Zowe-specific event processor. The purpose of this method is for internal + * Imperative APIs to get a properly initialized processor. This processor will be used + * when applications (like Zowe Explorer) call Imperative APIs that trigger events. For + * example, when the user updates credentials from Zowe Explorer, this processor could be + * used to emit an `OnVaultChanged` event. + * + * @internal Not meant to be called by application developers + * @static + * @returns {IZoweProcessor} The Zowe event processor instance. + * @throws {ImperativeError} If the application name is not recognized. + */ + public static getZoweProcessor(): IZoweProcessor { + return this.createProcessor("Zowe", IProcessorTypes.BOTH, Logger.getAppLogger()); + } + + /** + * Retrieves a generic event processor that can emit and watch events. + * + * @static + * @param {string} appName - The application name. + * @param {Logger} [logger] - Optional logger for the processor. + * @returns {IEmitterAndWatcher} An event processor capable of both emitting and watching. + * @throws {ImperativeError} If the application name is not recognized. + */ + public static getProcessor(appName: string, logger?: Logger): IEmitterAndWatcher { + return this.createProcessor(appName, IProcessorTypes.BOTH, logger); + } + + /** + * Retrieves a watcher-only event processor. + * + * @static + * @param {string} appName - The application name, defaults to "Zowe" if not specified. + * @param {Logger} [logger] - Optional logger for the processor. + * @returns {IWatcher} A watcher-only event processor. + * @throws {ImperativeError} If the application name is not recognized. + */ + public static getWatcher(appName: string = "Zowe", logger?: Logger): IWatcher { + return this.createProcessor(appName, IProcessorTypes.WATCHER, logger); + } + + /** + * Retrieves an emitter-only event processor. + * + * @static + * @param {string} appName - The application name. + * @param {Logger} [logger] - Optional logger for the processor. + * @returns {IEmitter} An emitter-only event processor. + * @throws {ImperativeError} If the application name is not recognized. + */ + public static getEmitter(appName: string, logger?: Logger): IEmitter { + return this.createProcessor(appName, IProcessorTypes.EMITTER, logger); + } + + /** + * Deletes a specific type of event processor (emitter). + * + * @static + * @param {string} appName - The application name associated with the emitter to be deleted. + */ + public static deleteEmitter(appName: string): void { + this.destroyProcessor(appName); + } + + /** + * Deletes a specific type of event processor (watcher). + * + * @static + * @param {string} appName - The application name associated with the watcher to be deleted. + */ + public static deleteWatcher(appName: string): void { + this.destroyProcessor(appName); + } + + /** + * Deletes an event processor, removing both its emitter and watcher capabilities. + * + * @static + * @param {string} appName - The application name whose processor is to be deleted. + */ + public static deleteProcessor(appName: string): void { + this.destroyProcessor(appName); + } + + /** + * Destroys a processor by removing all associated file watchers and cleaning up resources. + * + * @static + * @param {string} appName - The name of the application whose processor needs to be destroyed. + */ + private static destroyProcessor(appName: string): void { + const processor = this.instances.get(appName); + if (processor) { + processor.subscribedEvents.forEach((event, eventName) => { + event.subscriptions.forEach(subscription => subscription.removeAllListeners(eventName).close()); + }); + this.instances.delete(appName); + } + } +} \ No newline at end of file diff --git a/packages/imperative/src/events/src/EventProcessor.ts b/packages/imperative/src/events/src/EventProcessor.ts new file mode 100644 index 0000000000..f012da1f64 --- /dev/null +++ b/packages/imperative/src/events/src/EventProcessor.ts @@ -0,0 +1,189 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { Logger } from "../../logger/src/Logger"; +import { EventCallback, EventTypes } from "./EventConstants"; +import { ImperativeError } from "../../error/src/ImperativeError"; +import { Event } from "./Event"; +import { ConfigUtils } from "../../config/src/ConfigUtils"; +import { LoggerManager } from "../../logger/src/LoggerManager"; +import { ImperativeConfig } from "../../utilities"; +import { EventUtils } from "./EventUtils"; +import { IEventDisposable } from "./doc"; +import { IProcessorTypes } from "./doc/IEventInstanceTypes"; + +/** + * ## Overview + * Each EventProcessor manages its own subscriptions, handling the addition, emission, and removal of events. + * It uses a map where event names are keys, and values are Event objects that hold detailed event information and subscriptions. + * + * An `EventProcessor` handles three main functionalities: + * - **Subscribing to Events**: + * Registration of a callback function that will be executed when that event occurs. + * - **Emitting Events**: + * Notifying other applications or parts of the same application about certain actions or changes. + * - **Managing Event Subscriptions**: + * Mapping subscribed events and their corresponding callbacks, ensuring that events are properly handled and dispatched. + * + * ### Understanding Event Types + * - **Predefined Zowe Events**: + * Zowe provides a set of predefined shared and user events that can be watched. + * - **Custom Events**: + * Applications can define their own shared and user events, allowing for custom event-driven behavior. + * + * @export + * @class EventProcessor + */ +export class EventProcessor { + public subscribedEvents: Map = new Map(); + public eventTimes: Map; + public processorType: IProcessorTypes; + public appName: string; + public logger: Logger; + + /** + * Constructor initializes a new instance of EventProcessor. + * + * @param {string} appName - The application's name. + * @param {IProcessorTypes} type - The type of processor (Emitter, Watcher, or Both). + * @param {Logger} [logger] - Optional logger for recording events and errors. + * @throws {ImperativeError} If the application name is not recognized. + */ + public constructor(appName: string, type: IProcessorTypes, logger?: Logger) { + EventUtils.validateAppName(appName); + + this.subscribedEvents = new Map(); + this.eventTimes = new Map(); + this.appName = appName; + this.processorType = type; + + // Ensure correct environmental conditions to setup a custom logger, + // otherwise use default logger + if (ImperativeConfig.instance.loadedConfig == null || LoggerManager.instance.isLoggerInit === false) { + ConfigUtils.initImpUtils("zowe"); + } + this.logger = logger ?? Logger.getImperativeLogger(); + } + + private _subscribe(type: 'user' | 'shared', eventName: string, callbacks: EventCallback[] | EventCallback): IEventDisposable { + if (this.processorType === IProcessorTypes.EMITTER) { + throw new ImperativeError({ msg: `Processor does not have correct permissions: ${eventName}` }); + } + + let eventType; + if (type === "shared") { + eventType = EventUtils.isSharedEvent(eventName) ? EventTypes.ZoweSharedEvents : EventTypes.SharedEvents; + } else if (type === "user") { + eventType = EventUtils.isUserEvent(eventName) ? EventTypes.ZoweUserEvents : EventTypes.UserEvents; + } + + const disposable = EventUtils.createSubscription(this, eventName, eventType); + EventUtils.setupWatcher(this, eventName, callbacks); + return disposable; + } + /** + * Subscription to an event that will notify all subscribed users. + * + * @param {string} eventName - The name of the event to subscribe to. + * @param {EventCallback[] | EventCallback} callbacks - Callback functions to handle the event. + * @returns {IEventDisposable} - Object allowing management/cleanup of the subscription. + * @throws {ImperativeError} If the processor does not have the correct permissions to perform this action. + */ + public subscribeShared(eventName: string, callbacks: EventCallback[] | EventCallback): IEventDisposable { + return this._subscribe("shared", eventName, callbacks); + } + + /** + * Subscription to an event that will notify a single user. + * + * @param {string} eventName - The name of the event to subscribe to. + * @param {EventCallback[] | EventCallback} callbacks - Callback functions to handle the event. + * @returns {IEventDisposable} - Object allowing management/cleanup of the subscription. + * @throws {ImperativeError} If the processor does not have the correct permissions to perform this action. + */ + public subscribeUser(eventName: string, callbacks: EventCallback[] | EventCallback): IEventDisposable { + return this._subscribe("user", eventName, callbacks); + } + + /** + * Private method to emit the event + * @private + * @param eventName Event to be emitted + * @throws {ImperativeError} - If the event cannot be emitted. + */ + private emit(eventName: string) { + try { + const event = this.subscribedEvents.get(eventName) ?? EventUtils.createEvent(eventName, this.appName); + event.eventTime = new Date().toISOString(); + EventUtils.writeEvent(event); + } catch (err) { + throw new ImperativeError({ msg: `Error writing event: ${eventName}`, causeErrors: err }); + } + } + + /** + * Emits an event by updating its timestamp and writing event data. + * + * @param {string} eventName - The name of the event to emit. + * @throws {ImperativeError} If the processor does not have the correct permissions to perform this action. + * @throws {ImperativeError} - If the event cannot be emitted. + */ + public emitEvent(eventName: string): void { + if (this.processorType === IProcessorTypes.WATCHER) { + throw new ImperativeError({ msg: `Processor does not have correct permissions: ${eventName}` }); + } + if (EventUtils.isUserEvent(eventName) || EventUtils.isSharedEvent(eventName)) { + throw new ImperativeError({ msg: `Processor not allowed to emit Zowe events: ${eventName}` }); + } + this.emit(eventName); + } + + /** + * Specifically emits Zowe-related events, updating timestamps and handling data. + * + * @internal Internal Zowe emitter method + * @param {string} eventName - The name of the Zowe event to emit. + * @throws {ImperativeError} If the processor does not have the correct permissions to perform this action. + * @throws {ImperativeError} - If the event cannot be emitted. + */ + public emitZoweEvent(eventName: string): void { + if (this.appName !== "Zowe") { + throw new ImperativeError({ msg: `Processor does not have Zowe permissions: ${eventName}` }); + } + if (!EventUtils.isUserEvent(eventName) && !EventUtils.isSharedEvent(eventName)) { + throw new ImperativeError({ msg: `Invalid Zowe event: ${eventName}` }); + } + this.emit(eventName); + } + + /** + * Unsubscribes from an event, closing file watchers and cleaning up resources. + * + * @param {string} eventName - The name of the event to unsubscribe from. + * @throws {ImperativeError} If the processor does not have the correct permissions to perform this action. + * @throws {ImperativeError} - If unsubscribing fails. + */ + public unsubscribe(eventName: string): void { + if (this.processorType === IProcessorTypes.EMITTER) { + throw new ImperativeError({ msg: `Processor does not have correct permissions: ${eventName}` }); + } + const event = this.subscribedEvents.get(eventName); + if (event) { + event.subscriptions.forEach(subscription => { + subscription.removeAllListeners(eventName); + if (typeof subscription.close === 'function') { + subscription.close(); + } + }); + this.subscribedEvents.delete(eventName); + } + } +} \ No newline at end of file diff --git a/packages/imperative/src/events/src/EventUtils.ts b/packages/imperative/src/events/src/EventUtils.ts new file mode 100644 index 0000000000..7bf5a8e4f4 --- /dev/null +++ b/packages/imperative/src/events/src/EventUtils.ts @@ -0,0 +1,230 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ImperativeError } from "../../error/src/ImperativeError"; +import { join } from "path"; +import { ZoweUserEvents, ZoweSharedEvents, EventTypes, EventCallback } from "./EventConstants"; +import * as fs from "fs"; +import { ConfigUtils } from "../../config/src/ConfigUtils"; +import { IEventDisposable, IEventJson } from "./doc"; +import { Event } from "./Event"; +import { EventProcessor } from "./EventProcessor"; +import { ImperativeConfig } from "../../utilities/src/ImperativeConfig"; + +/** + * A collection of helper functions related to event processing, including: + * - directory management + * - event type determination + * - subscription creation and setting callbacks + * - event writing + */ +export class EventUtils { + + /** + * Retrieves a list of supported applications from configuration. + * + * @static + * @returns {string[]} List of application names. + * @throws If the extenders.json file cannot be created when it does not exist. + * @throws If the extenders.json file cannot be read. + */ + public static getListOfApps(): string[] { + const extendersJson = ConfigUtils.readExtendersJson(); + return ["Zowe", ...Object.keys(extendersJson.profileTypes)]; + } + + /** + * Won't throw an error if user entered a valid appName + * + * @static + * @param {string} appName - The name of the application. + * @throws {ImperativeError} If the application name is not recognized. + */ + public static validateAppName(appName: string): void { + const appList = this.getListOfApps(); + if (appList.includes(appName)) return; + // Performing `appList.find(app => app.includes(appName))` will allow for "tags" (or suffixes) coming from `getListOfApps()` + // However, we do not want this behavior because it will allow partial application names to be used + // Hence why we should probably match the application name with the exact profileType in `extenders.json` + throw new ImperativeError({ + msg: `Application name not found: ${appName}. Please use an application name from the list:\n- ${appList.join("\n- ")}` + }); + } + + /** + * Determines if the specified event name is associated with a user event. + * + * @param {string} eventName - The name of the event. + * @return {boolean} True if it is a user event, otherwise false. + */ + public static isUserEvent(eventName: string): boolean { + return Object.values(ZoweUserEvents).includes(eventName); + } + + /** + * Determines if the specified event name is associated with a shared event. + * + * @param {string} eventName - The name of the event. + * @return {boolean} True if it is a shared event, otherwise false. + */ + public static isSharedEvent(eventName: string): boolean { + return Object.values(ZoweSharedEvents).includes(eventName); + } + + /** + * Retrieve the event contents form disk + * + * @internal This is not intended for application developers + * @param eventFilePath The path to the event file + * @returns The object representing the Event + * @throws {ImperativeError} If the contents of the event cannot be retrieved. + */ + public static getEventContents(eventFilePath: string): IEventJson { + try { + return JSON.parse(fs.readFileSync(eventFilePath).toString()); + } catch (err) { + throw new ImperativeError({ msg: `Unable to retrieve event contents: Path: ${eventFilePath}` }); + } + } + + /** + * Determines the directory path for storing event files based on the event type and application name. + * + * @param {string} appName - The name of the application. + * @return {string} The directory path. + * @throws {ImperativeError} If the application name is not recognized. + */ + public static getEventDir(appName: string): string { + this.validateAppName(appName); + return join(".events", appName); + } + + /** + * Ensures that the specified directory for storing event files exists, creating it if necessary. + * + * @param {string} directoryPath - The path to the directory. + * @throws {ImperativeError} If we are unable to create the '.events' directory. + */ + public static ensureEventsDirExists(directoryPath: string) { + try { + if (!fs.existsSync(directoryPath)) { + fs.mkdirSync(directoryPath, { mode: 0o750, recursive: true }); // user read/write/exec, group read/exec + } + } catch (err) { + throw new ImperativeError({ msg: `Unable to create '.events' directory. Path: ${directoryPath}`, causeErrors: err }); + } + } + + /** + * Ensures that the specified file path for storing event data exists, creating it if necessary. + * + * @param {string} filePath - The path to the file. + * @throws {ImperativeError} If we are unable to create the event file required for event emission. + */ + public static ensureFileExists(filePath: string) { + try { + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + const fd = fs.openSync(filePath, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_RDWR, 0o640); + fs.closeSync(fd); + } catch (err) { + if (err.code !== 'EEXIST') { + throw new ImperativeError({ msg: `Unable to create event file. Path: ${filePath}`, causeErrors: err }); + } + } + } + + /** + * Create an event with minimal information + * + * @internal This is not intended for application developers + * @param eventName The name of the event. + * @param appName The name of the application. + * @returns The created event + * @throws {ImperativeError} If the application name is not recognized. + * @throws {ImperativeError} If we are unable to create the '.events' directory. + * @throws {ImperativeError} If we are unable to create the event file required for event emission. + */ + public static createEvent(eventName: string, appName: string): Event { + const zoweDir = ImperativeConfig.instance.loadedConfig != null ? ImperativeConfig.instance.cliHome : ConfigUtils.getZoweDir(); + const dir = join(zoweDir, EventUtils.getEventDir(appName)); + this.ensureEventsDirExists(dir); + + const filePath = join(dir, eventName); + this.ensureFileExists(filePath); + + return new Event({ + eventTime: new Date().toISOString(), + eventName: eventName, + appName: appName, + eventFilePath: filePath, + subscriptions: [], + }); + } + + /** + * Creates and registers a new event subscription for a specific event processor. + * + * @param {EventProcessor} eeInst - The event processor instance. + * @param {string} eventName - The name of the event. + * @param {EventTypes} eventType - The type of event. + * @return {IEventDisposable} An interface for managing the subscription. + * @throws {ImperativeError} If the application name is not recognized. + * @throws {ImperativeError} If we are unable to create the '.events' directory. + * @throws {ImperativeError} If we are unable to create the event file required for event emission. + */ + public static createSubscription(eeInst: EventProcessor, eventName: string, eventType: EventTypes): IEventDisposable { + const newEvent = EventUtils.createEvent(eventName, eeInst.appName); + newEvent.eventType = eventType; + eeInst.subscribedEvents.set(eventName, newEvent); + return { + close: () => eeInst.unsubscribe(eventName) + }; + } + + /** + * Sets up a file watcher for a specific event, triggering callbacks when the event file is updated. + * + * @param {EventProcessor} eeInst - The event processor instance. + * @param {string} eventName - The name of the event. + * @param {EventCallback[] | EventCallback} callbacks - A single callback or an array of callbacks to execute. + * @return {fs.FSWatcher} A file system watcher. + * @throws {ImperativeError} If the event to be watched does not have an existing file to watch. + * @throws {ImperativeError} Callbacks will fail if the contents of the event cannot be retrieved. + */ + public static setupWatcher(eeInst: EventProcessor, eventName: string, callbacks: EventCallback[] | EventCallback): fs.FSWatcher { + const event = eeInst.subscribedEvents.get(eventName); + const watcher = fs.watch(event.eventFilePath, (trigger: "rename" | "change") => { + // Accommodates for the delay between actual file change event and fsWatcher's perception + //(Node.JS triggers this notification event 3 times) + event.eventTime = EventUtils.getEventContents(event.eventFilePath).eventTime; + if (eeInst.eventTimes.get(eventName) !== event.eventTime) { + eeInst.logger.debug(`EventEmitter: Event "${trigger}" emitted: ${eventName}`); + if (Array.isArray(callbacks)) { + callbacks.forEach(cb => cb()); + } else { + callbacks(); + } + eeInst.eventTimes.set(eventName, event.eventTime); + } + }); + event.subscriptions.push(watcher); + return watcher; + } + + /** + * Writes event data to the corresponding event file in JSON format. + * + * @param {Event} event - The event object. + */ + public static writeEvent(event: Event) { + fs.writeFileSync(event.eventFilePath, JSON.stringify(event.toJson(), null, 2)); + } +} \ No newline at end of file diff --git a/packages/imperative/src/events/src/doc/IEventDisposable.ts b/packages/imperative/src/events/src/doc/IEventDisposable.ts new file mode 100644 index 0000000000..5dc7e58099 --- /dev/null +++ b/packages/imperative/src/events/src/doc/IEventDisposable.ts @@ -0,0 +1,24 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +/** + * Defines a contract for objects that can dispose of resources typically associated with an event. + * (Any object that implements this interface must provide an implementation of the close() method) + * @export + * @interface IEventDisposable + */ +export interface IEventDisposable { + /** + * Disposes of the actions registered to an event, effectively cleaning up or removing event handlers. + * @memberof IEventDisposable + */ + close(): void; +} diff --git a/packages/imperative/src/events/src/doc/IEventInstanceTypes.ts b/packages/imperative/src/events/src/doc/IEventInstanceTypes.ts new file mode 100644 index 0000000000..83615bfef0 --- /dev/null +++ b/packages/imperative/src/events/src/doc/IEventInstanceTypes.ts @@ -0,0 +1,49 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { EventCallback } from "../EventConstants"; +import { IEventDisposable } from "./IEventDisposable"; + +/** + * Interface for components that can subscribe to and unsubscribe from events. + * @interface IWatcher + */ +export interface IWatcher { + subscribeShared(eventName: string, callbacks: EventCallback[] | EventCallback): IEventDisposable; + subscribeUser(eventName: string, callbacks: EventCallback[] | EventCallback): IEventDisposable; + unsubscribe(eventName: string): void; +} + +/** + * Interface for components that can emit events. + * @interface IEmitter + */ +export interface IEmitter { + emitEvent(eventName: string): void; +} + +/** + * Interface for components that can both emit and watch events. + * Combines the capabilities of both IWatcher and IEmitter interfaces. + * @interface IEmitterAndWatcher + */ +export interface IEmitterAndWatcher extends IWatcher, IEmitter {} + +/** + * Enum representing the types of processors that can be used to handle events. + * Specifies whether the processor is a watcher, an emitter, or capable of both functions. + * @enum {string} + */ +export enum IProcessorTypes { + WATCHER = 'watcher', + EMITTER = 'emitter', + BOTH = 'both', +} \ No newline at end of file diff --git a/packages/imperative/src/events/src/doc/IEventJson.ts b/packages/imperative/src/events/src/doc/IEventJson.ts new file mode 100644 index 0000000000..85bbe6363c --- /dev/null +++ b/packages/imperative/src/events/src/doc/IEventJson.ts @@ -0,0 +1,45 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { EventTypes } from "../EventConstants"; +import * as fs from "fs"; + +/** + * Imperative Event JSON representation for user interpretation + * @export + * @interface IEventJson + */ +export interface IEventJson { + /** + * The time in which the event occurred + */ + eventTime: string; + /** + * The name of event that occurred + */ + eventName: string; + /** + * The application name that triggered the event + */ + appName: string; + /** + * The file path for information on the emitted event + */ + eventFilePath: string; + /** + * The type of event that occurred + */ + eventType?: EventTypes; + /** + * List of watchers to eventually close + */ + subscriptions?: fs.FSWatcher[]; +} diff --git a/packages/imperative/src/profiles/src/utils/index.ts b/packages/imperative/src/events/src/doc/index.ts similarity index 74% rename from packages/imperative/src/profiles/src/utils/index.ts rename to packages/imperative/src/events/src/doc/index.ts index bb4079679d..4a43ef166c 100644 --- a/packages/imperative/src/profiles/src/utils/index.ts +++ b/packages/imperative/src/events/src/doc/index.ts @@ -9,5 +9,6 @@ * */ -export * from "./ProfileIO"; -export * from "./ProfileUtils"; +export * from "./IEventDisposable"; +export * from "./IEventInstanceTypes"; +export * from "./IEventJson"; diff --git a/packages/imperative/src/expect/src/ImperativeExpect.ts b/packages/imperative/src/expect/src/ImperativeExpect.ts index 5e3cdf5e79..c1e8976481 100644 --- a/packages/imperative/src/expect/src/ImperativeExpect.ts +++ b/packages/imperative/src/expect/src/ImperativeExpect.ts @@ -87,7 +87,7 @@ export class ImperativeExpect { * @memberof ImperativeExpect */ public static toMatchRegExp(value: any, myRegex: string, msg?: string) { - if (!(new RegExp(myRegex).test(value))) { + if (!new RegExp(myRegex).test(value)) { throw new ImperativeError({msg: msg || "Input object/value does not match the regular expression"}, {tag: ImperativeExpect.ERROR_TAG}); } diff --git a/packages/imperative/src/imperative/__tests__/ConfigValidator.unit.test.ts b/packages/imperative/src/imperative/__tests__/ConfigValidator.unit.test.ts index bbee4d5c4b..43646c805e 100644 --- a/packages/imperative/src/imperative/__tests__/ConfigValidator.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/ConfigValidator.unit.test.ts @@ -9,7 +9,8 @@ * */ -import { ConfigurationValidator, IImperativeConfig } from "../index"; +import { IImperativeConfig } from ".."; +import { ConfigurationValidator } from "../src/ConfigurationValidator"; describe("Imperative should validate config provided by the consumer", () => { @@ -92,10 +93,11 @@ describe("Imperative should validate config provided by the consumer", () => { expect(false).toBe(true); } catch (e) { - expect(e.message) - .toContain("myProperty"); - expect(e.message) - .toContain("handler"); + expect(e.message).toContain( + 'Your Imperative profile configuration of type "myprofile" ' + + 'has the schema property "myProperty", which has multiple option definitions.' + ); + expect(e.message).toContain("Imperative is not be able to map multiple command line arguments to a single profile property."); } }); }); diff --git a/packages/imperative/src/imperative/__tests__/ConfigurationLoader.unit.test.ts b/packages/imperative/src/imperative/__tests__/ConfigurationLoader.unit.test.ts index ed29e8905b..de23bdb8d4 100644 --- a/packages/imperative/src/imperative/__tests__/ConfigurationLoader.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/ConfigurationLoader.unit.test.ts @@ -9,7 +9,7 @@ * */ -import { ConfigurationLoader } from ".."; +import { ConfigurationLoader } from "../src/ConfigurationLoader"; import { IImperativeOverrides } from "../src/doc/IImperativeOverrides"; import { IApimlSvcAttrs } from "../src/doc/IApimlSvcAttrs"; import { homedir } from "os"; diff --git a/packages/imperative/src/imperative/__tests__/Imperative.unit.test.ts b/packages/imperative/src/imperative/__tests__/Imperative.unit.test.ts index e54322d645..667ac0111f 100644 --- a/packages/imperative/src/imperative/__tests__/Imperative.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/Imperative.unit.test.ts @@ -21,9 +21,6 @@ import * as yargs from "yargs"; import { ImperativeError } from "../../error/src/ImperativeError"; describe("Imperative", () => { - // eslint-disable-next-line deprecation/deprecation - const mainModule = process.mainModule; - const loadImperative = () => { return require("../src/Imperative").Imperative; }; @@ -42,7 +39,6 @@ describe("Imperative", () => { jest.doMock("../../logger/src/Logger"); jest.doMock("../src/env/EnvironmentalVariableSettings"); jest.doMock("../src/auth/builders/CompleteAuthGroupBuilder"); - jest.doMock("../src/profiles/builders/CompleteProfilesGroupBuilder"); jest.doMock("../src/config/cmd/auto-init/builders/CompleteAutoInitCommandBuilder"); jest.doMock("../../config/src/Config"); jest.doMock("../../security/src/CredentialManagerFactory"); @@ -59,7 +55,6 @@ describe("Imperative", () => { const { Logger } = require("../../logger"); const { EnvironmentalVariableSettings } = require("../src/env/EnvironmentalVariableSettings"); const { CompleteAuthGroupBuilder } = require("../src/auth/builders/CompleteAuthGroupBuilder"); - const { CompleteProfilesGroupBuilder } = require("../src/profiles/builders/CompleteProfilesGroupBuilder"); const { CompleteAutoInitCommandBuilder } = require("../src/config/cmd/auto-init/builders/CompleteAutoInitCommandBuilder"); const { Config } = require("../../config/src/Config"); const { CredentialManagerFactory } = require("../../security/src/CredentialManagerFactory"); @@ -86,9 +81,6 @@ describe("Imperative", () => { CompleteAuthGroupBuilder: { getAuthGroup: CompleteAuthGroupBuilder.getAuthGroup as Mock }, - CompleteProfilesGroupBuilder: { - getProfileGroup: CompleteProfilesGroupBuilder.getProfileGroup as Mock - }, CompleteAutoInitCommandBuilder: { getAutoInitCommand: CompleteAutoInitCommandBuilder.getAutoInitCommand as Mock< typeof CompleteAutoInitCommandBuilder.getAutoInitCommand @@ -134,11 +126,6 @@ describe("Imperative", () => { }; beforeEach(() => { - // eslint-disable-next-line deprecation/deprecation - (process.mainModule as any) = { - filename: __filename - }; - jest.resetModules(); // Refresh the imperative load every time @@ -152,11 +139,6 @@ describe("Imperative", () => { Imperative.getPreparedCmdTree = jest.fn(() => mockCmdTree); }); - afterEach(() => { - // eslint-disable-next-line deprecation/deprecation - process.mainModule = mainModule; - }); - describe("init", () => { let defaultConfig = { name: "test-cli", @@ -193,7 +175,7 @@ describe("Imperative", () => { expect(result).toBeUndefined(); expect(mocks.Config.load).toHaveBeenCalledTimes(1); expect(mocks.OverridesLoader.load).toHaveBeenCalledTimes(1); - expect(mocks.OverridesLoader.load).toHaveBeenCalledWith(defaultConfig, { version: 10000, name: "sample" }); + expect(mocks.OverridesLoader.load).toHaveBeenCalledWith(defaultConfig, { version: 10000, name: "sample", zoweVersion: "V99" }); }); describe("AppSettings", () => { @@ -359,11 +341,11 @@ describe("Imperative", () => { beforeEach(() => { loggingConfig = mocks.LoggingConfigurer.configureLogger("dont care", {}); - envConfig = mocks.EnvironmentalVariableSettings.read(Imperative.envVariablePrefix); + envConfig = mocks.EnvironmentalVariableSettings.read(mocks.ImperativeConfig.instance.envVariablePrefix); }); it("should know what the envVariablePrefix is [DEPRECATED]", async () => { - expect(Imperative.envVariablePrefix).toEqual(defaultConfig.name); + expect(mocks.ImperativeConfig.instance.envVariablePrefix).toEqual(defaultConfig.name); }); it("should handle a valid imperative log level", async () => { @@ -626,41 +608,6 @@ describe("Imperative", () => { }] }; - it("should call getProfileGroup when we need to auto-generate commands", () => { - /* addAutoGeneratedCommands calls ImperativeConfig.instance.loadedConfig. - * getLoadedConfig is a getter of a property, so mock we the property. - * We need loadedConfig.autoGenerateProfileCommands to be null and - * loadedConfig.profiles to have something in it. - */ - Object.defineProperty(mocks.ImperativeConfig.instance, "loadedConfig", { - configurable: true, - get: jest.fn(() => fakeConfig) - }); - - const autoGenCmdTree = Imperative.addAutoGeneratedCommands(JSON.parse(JSON.stringify(mockRootCmdTree))); - expect(mocks.CompleteProfilesGroupBuilder.getProfileGroup).toHaveBeenCalledTimes(1); - expect(autoGenCmdTree.children.length).toBe(2); - }); - - it("should add base profile in getProfileGroup when it is defined in Imperative config", () => { - /* addAutoGeneratedCommands calls ImperativeConfig.instance.loadedConfig. - * getLoadedConfig is a getter of a property, so mock we the property. - * We need loadedConfig.autoGenerateProfileCommands to be null and - * loadedConfig.profiles to have something in it. - */ - Object.defineProperty(mocks.ImperativeConfig.instance, "loadedConfig", { - configurable: true, - get: jest.fn(() => { - return { ...fakeConfig, baseProfile: fakeConfig.profiles[0] }; - }) - }); - - const autoGenCmdTree = Imperative.addAutoGeneratedCommands(JSON.parse(JSON.stringify(mockRootCmdTree))); - expect(mocks.CompleteProfilesGroupBuilder.getProfileGroup).toHaveBeenCalledTimes(1); - expect(mocks.CompleteProfilesGroupBuilder.getProfileGroup.mock.calls[0][0].length).toBe(2); - expect(autoGenCmdTree.children.length).toBe(2); - }); - it("should add auth service in getAuthGroup when it is defined in Imperative config", () => { /* addAutoGeneratedCommands calls ImperativeConfig.instance.loadedConfig. * getLoadedConfig is a getter of a property, so mock we the property. @@ -701,8 +648,8 @@ describe("Imperative", () => { const autoGenCmdTree = Imperative.addAutoGeneratedCommands(JSON.parse(JSON.stringify(mockRootCmdTree))); expect(mocks.CompleteAuthGroupBuilder.getAuthGroup).toHaveBeenCalledTimes(1); - // Expect 3 command groups added (auth, config and profiles) - expect(autoGenCmdTree.children.length).toBe(3); + // Expect 2 command groups added (auth and config) + expect(autoGenCmdTree.children.length).toBe(2); }); it("should add auto init in the config group when it is defined in Imperative config", () => { diff --git a/packages/imperative/src/imperative/__tests__/LoggingConfigurer.unit.test.ts b/packages/imperative/src/imperative/__tests__/LoggingConfigurer.unit.test.ts index ba39b217b7..331e51d919 100644 --- a/packages/imperative/src/imperative/__tests__/LoggingConfigurer.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/LoggingConfigurer.unit.test.ts @@ -22,6 +22,7 @@ describe("LoggingConfigurer tests", () => { beforeAll(() => { jest.spyOn(os, "homedir").mockImplementation(() => fakeHome); jest.spyOn(path, "normalize").mockImplementation((p: string) => p); + jest.spyOn(path.posix, "join").mockImplementation((...ps: string[]) => ps.join("/")); }); afterAll(() => { diff --git a/packages/imperative/src/imperative/__tests__/OverridesLoader.unit.test.ts b/packages/imperative/src/imperative/__tests__/OverridesLoader.unit.test.ts index 73870fe00a..3baa73b1d1 100644 --- a/packages/imperative/src/imperative/__tests__/OverridesLoader.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/OverridesLoader.unit.test.ts @@ -23,8 +23,6 @@ import { AppSettings } from "../../settings"; const TEST_MANAGER_NAME = "test manager"; describe("OverridesLoader", () => { - // eslint-disable-next-line deprecation/deprecation - const mainModule = process.mainModule; const mockCredMgrInitialized = jest.fn().mockReturnValue(false); beforeAll(() => { @@ -34,15 +32,6 @@ describe("OverridesLoader", () => { beforeEach(() => { jest.restoreAllMocks(); jest.resetAllMocks(); - // eslint-disable-next-line deprecation/deprecation - (process.mainModule as any) = { - filename: __filename - }; - }); - - afterEach(() => { - // eslint-disable-next-line deprecation/deprecation - process.mainModule = mainModule; }); afterAll(() => { @@ -217,9 +206,8 @@ describe("OverridesLoader", () => { }; // DON'T YOU EVER DO THIS AFTER THE SPY, IT WILL CAUSE YOU MASSIVE PROBLEMS - // I suspect that process.mainModule.filename somehow uses path.resolve (25 times when I ran this) - // eslint-disable-next-line deprecation/deprecation - const expectedArgs = [process.mainModule.filename, "../", config.overrides.CredentialManager]; + // I suspect that require.main.filename somehow uses path.resolve (25 times when I ran this) + const expectedArgs = [__filename, "../", config.overrides?.CredentialManager]; const expectedLocation = "/some/random/dummy/location/DummyFile.ts"; jest.spyOn(path, "resolve").mockReturnValueOnce(expectedLocation); diff --git a/packages/imperative/src/imperative/__tests__/__snapshots__/LoggingConfigurer.unit.test.ts.snap b/packages/imperative/src/imperative/__tests__/__snapshots__/LoggingConfigurer.unit.test.ts.snap index 17e253d54a..a9ab1667a6 100644 --- a/packages/imperative/src/imperative/__tests__/__snapshots__/LoggingConfigurer.unit.test.ts.snap +++ b/packages/imperative/src/imperative/__tests__/__snapshots__/LoggingConfigurer.unit.test.ts.snap @@ -6,7 +6,7 @@ Object { "appenders": Object { "app": Object { "backups": 5, - "filename": "./someHome/sample/logs/sample.log", + "filename": "./someHome/logs/sample.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -16,7 +16,7 @@ Object { }, "default": Object { "backups": 5, - "filename": "./someHome/imperative/logs/imperative.log", + "filename": "./someHome/logs/imperative.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -26,7 +26,7 @@ Object { }, "imperative": Object { "backups": 5, - "filename": "./someHome/imperative/logs/imperative.log", + "filename": "./someHome/logs/imperative.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -77,7 +77,7 @@ Object { }, "default": Object { "backups": 5, - "filename": "./someHome/imperative/logs/imperative.log", + "filename": "./someHome/logs/imperative.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -87,7 +87,7 @@ Object { }, "imperative": Object { "backups": 5, - "filename": "./someHome/imperative/logs/imperative.log", + "filename": "./someHome/logs/imperative.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -136,7 +136,7 @@ Object { }, "default": Object { "backups": 5, - "filename": "./someHome/imperative/logs/imperative.log", + "filename": "./someHome/logs/imperative.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -146,7 +146,7 @@ Object { }, "extraOne": Object { "backups": 5, - "filename": "./someHome/extraOne/logs/extraOne.log", + "filename": "./someHome/logs/extraOne.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -166,7 +166,7 @@ Object { }, "imperative": Object { "backups": 5, - "filename": "./someHome/imperative/logs/imperative.log", + "filename": "./someHome/logs/imperative.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -217,7 +217,7 @@ Object { "appenders": Object { "app": Object { "backups": 5, - "filename": "./someHome/sample/logs/sample.log", + "filename": "./someHome/logs/sample.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -227,7 +227,7 @@ Object { }, "default": Object { "backups": 5, - "filename": "./someHome/imperative/logs/imperative.log", + "filename": "./someHome/logs/imperative.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -237,7 +237,7 @@ Object { }, "imperative": Object { "backups": 5, - "filename": "./someHome/imperative/logs/imperative.log", + "filename": "./someHome/logs/imperative.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -276,7 +276,7 @@ Object { "appenders": Object { "app": Object { "backups": 5, - "filename": "./someHome/notSample/logs/notSample.log", + "filename": "./someHome/logs/notSample.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -286,7 +286,7 @@ Object { }, "default": Object { "backups": 5, - "filename": "./someHome/imperative/logs/imperative.log", + "filename": "./someHome/logs/imperative.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -296,7 +296,7 @@ Object { }, "imperative": Object { "backups": 5, - "filename": "./someHome/imperative/logs/imperative.log", + "filename": "./someHome/logs/imperative.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -335,7 +335,7 @@ Object { "appenders": Object { "app": Object { "backups": 5, - "filename": "./someHome/sample/logs/sample.log", + "filename": "./someHome/logs/sample.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -345,7 +345,7 @@ Object { }, "default": Object { "backups": 5, - "filename": "./someHome/imperative/logs/imperative.log", + "filename": "./someHome/logs/imperative.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -355,7 +355,7 @@ Object { }, "imperative": Object { "backups": 5, - "filename": "./someHome/imperative/logs/imperative.log", + "filename": "./someHome/logs/imperative.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -394,7 +394,7 @@ Object { "appenders": Object { "app": Object { "backups": 5, - "filename": "./someHome/sample/logs/sample.log", + "filename": "./someHome/logs/sample.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -404,7 +404,7 @@ Object { }, "default": Object { "backups": 5, - "filename": "./someHome/imperative/logs/imperative.log", + "filename": "./someHome/logs/imperative.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -414,7 +414,7 @@ Object { }, "imperative": Object { "backups": 5, - "filename": "./someHome/imperative/logs/imperative.log", + "filename": "./someHome/logs/imperative.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", diff --git a/packages/imperative/src/imperative/__tests__/config/cmd/auto-init/BaseAutoInitHandler.unit.test.ts b/packages/imperative/src/imperative/__tests__/config/cmd/auto-init/BaseAutoInitHandler.unit.test.ts index c234a30523..561e3cf49e 100644 --- a/packages/imperative/src/imperative/__tests__/config/cmd/auto-init/BaseAutoInitHandler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/config/cmd/auto-init/BaseAutoInitHandler.unit.test.ts @@ -10,7 +10,7 @@ */ import { IHandlerParameters } from "../../../../../cmd"; -import { ImperativeConfig, ProcessUtils } from "../../../../../utilities"; +import { ImperativeConfig, ProcessUtils, TextUtils } from "../../../../../utilities"; import { FakeAutoInitHandler } from "./__data__/FakeAutoInitHandler"; import * as lodash from "lodash"; import * as jestDiff from "jest-diff"; @@ -33,11 +33,7 @@ const mockParams: IHandlerParameters = { }, arguments: {}, // To be defined by individual tests positionals: ["config", "auto-init"], - profiles: { - getMeta: jest.fn(() => ({ - name: "fakeName" - })) - } + profiles: {} } as any; describe("BaseAutoInitHandler", () => { @@ -61,6 +57,20 @@ describe("BaseAutoInitHandler", () => { } }; stripAnsiSpy = (stripAnsi as any).mockImplementation(() => jest.requireActual("strip-ansi")); + + // Pretend that wordWrap and chalk work. We do not care about their output in these tests. + jest.spyOn(TextUtils, "wordWrap").mockReturnValue("Fake wrapped text"); + + Object.defineProperty(TextUtils, "chalk", { + configurable: true, + get: jest.fn(() => { + return { + yellowBright: jest.fn(() => { + return "Fake yellow in some text"; + }) + }; + }) + }); }); afterEach(() => { @@ -106,9 +116,9 @@ describe("BaseAutoInitHandler", () => { } expect(caughtError).toBeUndefined(); - expect(doInitSpy).toBeCalledTimes(1); - expect(processAutoInitSpy).toBeCalledTimes(1); - expect(createSessCfgFromArgsSpy).toBeCalledTimes(1); + expect(doInitSpy).toHaveBeenCalledTimes(1); + expect(processAutoInitSpy).toHaveBeenCalledTimes(1); + expect(createSessCfgFromArgsSpy).toHaveBeenCalledTimes(1); expect(mockConfigApi.layers.merge).toHaveBeenCalledTimes(1); expect(mockConfigApi.layers.write).toHaveBeenCalledTimes(0); expect(mockConfigApi.layers.get).toHaveBeenCalledTimes(1); @@ -168,14 +178,14 @@ describe("BaseAutoInitHandler", () => { const mSession: Session = doInitSpy.mock.calls[0][0] as any; expect(caughtError).toBeUndefined(); - expect(doInitSpy).toBeCalledTimes(1); + expect(doInitSpy).toHaveBeenCalledTimes(1); expect(mSession.ISession.user).toBeUndefined(); expect(mSession.ISession.password).toBeUndefined(); expect(mSession.ISession.base64EncodedAuth).toBeUndefined(); expect(mSession.ISession.cert).toBeUndefined(); expect(mSession.ISession.certKey).toBeUndefined(); - expect(processAutoInitSpy).toBeCalledTimes(1); - expect(createSessCfgFromArgsSpy).toBeCalledTimes(1); + expect(processAutoInitSpy).toHaveBeenCalledTimes(1); + expect(createSessCfgFromArgsSpy).toHaveBeenCalledTimes(1); expect(mockConfigApi.layers.merge).toHaveBeenCalledTimes(1); expect(mockConfigApi.layers.write).toHaveBeenCalledTimes(0); expect(mockConfigApi.layers.get).toHaveBeenCalledTimes(1); @@ -224,9 +234,9 @@ describe("BaseAutoInitHandler", () => { } expect(caughtError).toBeUndefined(); - expect(doInitSpy).toBeCalledTimes(1); - expect(processAutoInitSpy).toBeCalledTimes(1); - expect(createSessCfgFromArgsSpy).toBeCalledTimes(1); + expect(doInitSpy).toHaveBeenCalledTimes(1); + expect(processAutoInitSpy).toHaveBeenCalledTimes(1); + expect(createSessCfgFromArgsSpy).toHaveBeenCalledTimes(1); expect(promptFunction).toHaveBeenCalledTimes(2); expect(mockConfigApi.layers.merge).toHaveBeenCalledTimes(1); expect(mockConfigApi.layers.write).toHaveBeenCalledTimes(0); @@ -288,9 +298,9 @@ describe("BaseAutoInitHandler", () => { } expect(caughtError).toBeUndefined(); - expect(doInitSpy).toBeCalledTimes(1); - expect(processAutoInitSpy).toBeCalledTimes(1); - expect(createSessCfgFromArgsSpy).toBeCalledTimes(1); + expect(doInitSpy).toHaveBeenCalledTimes(1); + expect(processAutoInitSpy).toHaveBeenCalledTimes(1); + expect(createSessCfgFromArgsSpy).toHaveBeenCalledTimes(1); expect(mockConfigApi.layers.merge).toHaveBeenCalledTimes(1); expect(mockConfigApi.layers.write).toHaveBeenCalledTimes(0); expect(mockSave).toHaveBeenCalledTimes(0); @@ -345,9 +355,9 @@ describe("BaseAutoInitHandler", () => { } expect(caughtError).toBeUndefined(); - expect(doInitSpy).toBeCalledTimes(1); - expect(processAutoInitSpy).toBeCalledTimes(1); - expect(createSessCfgFromArgsSpy).toBeCalledTimes(1); + expect(doInitSpy).toHaveBeenCalledTimes(1); + expect(processAutoInitSpy).toHaveBeenCalledTimes(1); + expect(createSessCfgFromArgsSpy).toHaveBeenCalledTimes(1); expect(mockConfigApi.layers.merge).toHaveBeenCalledTimes(1); expect(mockConfigApi.layers.write).toHaveBeenCalledTimes(0); expect(mockSave).toHaveBeenCalledTimes(1); @@ -400,9 +410,9 @@ describe("BaseAutoInitHandler", () => { } expect(caughtError).toBeUndefined(); - expect(doInitSpy).toBeCalledTimes(1); - expect(processAutoInitSpy).toBeCalledTimes(1); - expect(createSessCfgFromArgsSpy).toBeCalledTimes(1); + expect(doInitSpy).toHaveBeenCalledTimes(1); + expect(processAutoInitSpy).toHaveBeenCalledTimes(1); + expect(createSessCfgFromArgsSpy).toHaveBeenCalledTimes(1); expect(mockConfigApi.layers.merge).toHaveBeenCalledTimes(0); expect(mockConfigApi.layers.write).toHaveBeenCalledTimes(0); expect(mockSave).toHaveBeenCalledTimes(1); @@ -476,9 +486,9 @@ describe("BaseAutoInitHandler", () => { } expect(caughtError).toBeUndefined(); - expect(doInitSpy).toBeCalledTimes(1); - expect(processAutoInitSpy).toBeCalledTimes(1); - expect(createSessCfgFromArgsSpy).toBeCalledTimes(1); + expect(doInitSpy).toHaveBeenCalledTimes(1); + expect(processAutoInitSpy).toHaveBeenCalledTimes(1); + expect(createSessCfgFromArgsSpy).toHaveBeenCalledTimes(1); expect(mockConfigApi.layers.merge).toHaveBeenCalledTimes(1); expect(mockConfigApi.layers.write).toHaveBeenCalledTimes(0); expect(mockSave).toHaveBeenCalledTimes(0); diff --git a/packages/imperative/src/imperative/__tests__/config/cmd/auto-init/__snapshots__/CompleteAutoInitCommandBuilder.unit.test.ts.snap b/packages/imperative/src/imperative/__tests__/config/cmd/auto-init/__snapshots__/CompleteAutoInitCommandBuilder.unit.test.ts.snap index 5010bd08a5..43dac4bc98 100644 --- a/packages/imperative/src/imperative/__tests__/config/cmd/auto-init/__snapshots__/CompleteAutoInitCommandBuilder.unit.test.ts.snap +++ b/packages/imperative/src/imperative/__tests__/config/cmd/auto-init/__snapshots__/CompleteAutoInitCommandBuilder.unit.test.ts.snap @@ -58,6 +58,17 @@ Object { "name": "edit", "type": "boolean", }, + Object { + "aliases": Array [ + "ed", + ], + "description": "Editor that overrides the default editor for this file type. Set the option to the editor's executable file location or the program's name: ie \\"--editor notepad\\"", + "implies": Array [ + "edit", + ], + "name": "editor", + "type": "string", + }, Object { "aliases": Array [ "ow", diff --git a/packages/imperative/src/imperative/__tests__/config/cmd/convert-profiles/convert-profiles.handler.unit.test.ts b/packages/imperative/src/imperative/__tests__/config/cmd/convert-profiles/convert-profiles.handler.unit.test.ts index 7d9c66e7df..7df77d6800 100644 --- a/packages/imperative/src/imperative/__tests__/config/cmd/convert-profiles/convert-profiles.handler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/config/cmd/convert-profiles/convert-profiles.handler.unit.test.ts @@ -9,23 +9,13 @@ * */ -import * as fs from "fs"; -import * as fsExtra from "fs-extra"; -import { keyring as keytar } from "@zowe/secrets-for-zowe-sdk"; -import { Config, ConfigBuilder, ConfigSchema } from "../../../../../config"; +import { ConvertV1Profiles } from "../../../../../config"; import { IHandlerParameters } from "../../../../../cmd"; -import { ProfileIO } from "../../../../../profiles"; -import { AppSettings } from "../../../../../settings"; -import { ImperativeConfig } from "../../../../../utilities"; -import * as npmInterface from "../../../../src/plugins/utilities/npm-interface"; -import { PluginIssues } from "../../../../src/plugins/utilities/PluginIssues"; -import ConvertProfilesHandler from "../../../../src/config/cmd/convert-profiles/convert-profiles.handler"; -jest.mock("../../../../src/plugins/utilities/npm-interface"); -jest.mock("../../../../../imperative/src/OverridesLoader"); +import ConvertProfilesHandler from "../../../../src/config/cmd/convert-profiles/convert-profiles.handler"; -let stdout: string; -let stderr: string; +let stdout: string = ""; +let stderr: string = ""; const getIHandlerParametersObject = (): IHandlerParameters => { const x: any = { @@ -46,7 +36,10 @@ const getIHandlerParametersObject = (): IHandlerParameters => { stderr += errors; }), errorHeader: jest.fn(() => undefined), - prompt: jest.fn() + prompt: jest.fn((promptString) => { + stdout += promptString; + return "y"; + }) } }, arguments: {}, @@ -55,712 +48,145 @@ const getIHandlerParametersObject = (): IHandlerParameters => { }; describe("Configuration Convert Profiles command handler", () => { - let mockImperativeConfig: any; - - beforeEach(() => { - mockImperativeConfig = { - cliHome: __dirname, - config: { - api: { - layers: { - activate: jest.fn(), - merge: jest.fn() - } - }, - layerActive: jest.fn().mockReturnValue({}), - save: jest.fn(), - exists: false - } - }; - stdout = stderr = ""; - jest.spyOn(ImperativeConfig, "instance", "get").mockReturnValue(mockImperativeConfig); - }); - - afterEach(() => { - jest.resetAllMocks(); - }); - - it("should do nothing if there are no old plug-ins or profiles", async () => { - const handler = new ConvertProfilesHandler(); - jest.spyOn(handler as any, "getOldPluginInfo").mockReturnValueOnce({ plugins: [], overrides: [] }); - jest.spyOn(handler as any, "getOldProfileCount").mockReturnValueOnce(0); - const params = getIHandlerParametersObject(); - - await handler.process(params); - expect(stdout).toContain("No old profiles were found"); - expect(stderr).toBe(""); - }); - - it("should remove obsolete plug-ins", async () => { - const oldPluginInfo = { - plugins: ["pluginA", "pluginB"], - overrides: ["overrideX"] - }; - const handler = new ConvertProfilesHandler(); - jest.spyOn(handler as any, "getOldPluginInfo").mockReturnValueOnce(oldPluginInfo); - jest.spyOn(handler as any, "getOldProfileCount").mockReturnValueOnce(0); - jest.spyOn(PluginIssues, "instance", "get").mockReturnValue({ - getInstalledPlugins: jest.fn().mockReturnValue({ "pluginA": null, "pluginB": null }) - } as any); - const removeOverrideSpy = jest.spyOn(handler as any, "removeOverride").mockImplementation(); - const uninstallSpy = jest.spyOn(npmInterface, "uninstall") - .mockImplementationOnce(() => { throw new Error("invalid plugin"); }) - .mockImplementation(); - const params = getIHandlerParametersObject(); - params.arguments.prompt = false; - - await handler.process(params); - expect(stdout).toContain("The following plug-ins will be removed"); - expect(stdout).toContain("Uninstalled plug-in: pluginB"); - expect(stderr).toContain("Failed to uninstall plug-in \"pluginA\""); - expect(removeOverrideSpy).toHaveBeenCalledWith("overrideX", 0, ["overrideX"]); - expect(uninstallSpy).toHaveBeenCalledTimes(2); - }); - - it("should convert old profiles", async () => { - const metaError = new Error("invalid meta file"); - const profileError = new Error("invalid profile file"); - jest.spyOn(ConfigBuilder, "convert").mockResolvedValueOnce({ - config: Config.empty(), - profilesConverted: { - fruit: ["apple", "coconut"] - }, - profilesFailed: [ - { name: "banana", type: "fruit", error: profileError }, - { type: "fruit", error: metaError } - ] - }); - const updateSchemaSpy = jest.spyOn(ConfigSchema, "updateSchema").mockReturnValueOnce(undefined); - jest.spyOn(fs, "renameSync").mockReturnValueOnce(); - - const handler = new ConvertProfilesHandler(); - jest.spyOn(handler as any, "getOldPluginInfo").mockReturnValueOnce({ plugins: [], overrides: [] }); - jest.spyOn(handler as any, "getOldProfileCount").mockReturnValueOnce(3); - const params = getIHandlerParametersObject(); - params.arguments.prompt = false; - - await handler.process(params); - expect(stdout).toContain("Detected 3 old profile(s)"); - expect(stdout).toContain("Converted fruit profiles: apple, coconut"); - expect(stderr).toContain("Failed to load fruit profile \"banana\""); - expect(stderr).toContain(profileError.message); - expect(stderr).toContain("Failed to find default fruit profile"); - expect(stderr).toContain(metaError.message); - expect(updateSchemaSpy).toHaveBeenCalled(); - expect(mockImperativeConfig.config.save).toHaveBeenCalled(); - }); - - it("should not convert old profiles if team config already exists", async () => { - jest.spyOn(ConfigBuilder, "convert").mockResolvedValueOnce({ - config: Config.empty(), - profilesConverted: { - fruit: ["apple", "coconut", "banana"] - }, - profilesFailed: [] - }); - mockImperativeConfig.config.exists = true; - const updateSchemaSpy = jest.spyOn(ConfigSchema, "updateSchema").mockReturnValueOnce(undefined); - jest.spyOn(fs, "renameSync").mockReturnValueOnce(); - - const handler = new ConvertProfilesHandler(); - jest.spyOn(handler as any, "getOldPluginInfo").mockReturnValueOnce({ plugins: [], overrides: [] }); - jest.spyOn(handler as any, "getOldProfileCount").mockReturnValueOnce(3); - const params = getIHandlerParametersObject(); - params.arguments.prompt = false; - - await handler.process(params); - expect(stdout).toContain("A team configuration file was detected"); - expect(stdout).toContain("No old profiles were found"); - expect(stdout).not.toContain("Converted fruit profiles: apple, coconut"); - expect(updateSchemaSpy).not.toHaveBeenCalled(); - expect(mockImperativeConfig.config.save).not.toHaveBeenCalled(); - }); - - it("should remove plug-ins and convert profiles if prompt is accepted", async () => { - const configConvertSpy = jest.spyOn(ConfigBuilder, "convert").mockResolvedValueOnce({ - config: Config.empty(), - profilesConverted: {}, - profilesFailed: [] - }); - jest.spyOn(ConfigSchema, "updateSchema").mockReturnValueOnce(undefined); - jest.spyOn(fs, "renameSync").mockReturnValueOnce(); - - const handler = new ConvertProfilesHandler(); - jest.spyOn(handler as any, "getOldPluginInfo").mockReturnValueOnce({ plugins: ["fake-plugin"], overrides: [] }); - jest.spyOn(handler as any, "getOldProfileCount").mockReturnValueOnce(1); - jest.spyOn(PluginIssues, "instance", "get").mockReturnValue({ - getInstalledPlugins: jest.fn().mockReturnValue({ "fake-plugin": null }) - } as any); - const uninstallSpy = jest.spyOn(npmInterface, "uninstall").mockImplementation(); - const params = getIHandlerParametersObject(); - (params.response.console.prompt as any).mockResolvedValueOnce("y"); - - await handler.process(params); - expect(stdout).toContain("Detected 1 old profile(s)"); - expect(stdout).toContain("The following plug-ins will be removed"); - expect(stdout).toContain("Your new profiles have been saved"); - expect(stdout).toContain("Your old profiles have been moved"); - expect(stderr).toBe(""); - expect(uninstallSpy).toHaveBeenCalled(); - expect(configConvertSpy).toHaveBeenCalled(); - }); + const convProfHandler = new ConvertProfilesHandler(); + let convertSpy: any; + + const fakeConvertResult = { + msgs: [ + { msgFormat: 1, msgText: "Report Msg 1" }, + { msgFormat: 1, msgText: "Report Msg 2" }, + { msgFormat: 2, msgText: "Error Msg 1" }, + { msgFormat: 2, msgText: "Error Msg 2" } + ], + v1ScsPluginName: null as any, + credsWereMigrated: true, + cfgFilePathNm: ConvertV1Profiles["noCfgFilePathNm"], + numProfilesFound: 0, + profilesConverted: { + zosmf: ["zosmfProfNm1", "zosmfProfNm2", "zosmfProfNm3"], + tso: ["tsoProfNm1", "tsoProfNm2", "tsoProfNm3"], + ssh: ["sshProfNm1", "sshProfNm2", "sshProfNm3"] + }, + profilesFailed: [ + { name: "zosmfProfNm4:", type: "zosmf", error: new Error("This profile stinks") }, + { name: "zosmfProfNm5:", type: "zosmf", error: new Error("This profile also stinks") } + ] + }; - it("should do nothing if prompt is rejected", async () => { - const configConvertSpy = jest.spyOn(ConfigBuilder, "convert"); + it("should report a set of converted profiles and NOT do any prompt", async () => { + // pretend that convert works + convertSpy = jest.spyOn(ConvertV1Profiles, "convert").mockResolvedValue(Promise.resolve(fakeConvertResult)); - const handler = new ConvertProfilesHandler(); - jest.spyOn(handler as any, "getOldPluginInfo").mockReturnValueOnce({ plugins: ["fake-plugin"], overrides: [] }); - jest.spyOn(handler as any, "getOldProfileCount").mockReturnValueOnce(1); - const uninstallSpy = jest.spyOn(npmInterface, "uninstall"); + // call the function that we want to test const params = getIHandlerParametersObject(); - (params.response.console.prompt as any).mockResolvedValueOnce("n"); - - await handler.process(params); - expect(stdout).toContain("Detected 1 old profile(s)"); - expect(stdout).toContain("The following plug-ins will be removed"); - expect(stderr).toBe(""); - expect(uninstallSpy).not.toHaveBeenCalled(); - expect(configConvertSpy).not.toHaveBeenCalled(); - }); + await convProfHandler.process(params); - it("should remove existing profiles and delete secure properties", async () => { - const metaError = new Error("invalid meta file"); - jest.spyOn(ConfigBuilder, "convert").mockResolvedValueOnce({ - config: Config.empty(), - profilesConverted: { - fruit: ["apple", "coconut", "banana"] - }, - profilesFailed: [] - }); - const updateSchemaSpy = jest.spyOn(ConfigSchema, "updateSchema").mockReturnValueOnce(undefined); - jest.spyOn(fs, "renameSync").mockReturnValueOnce(); - jest.spyOn(keytar, "findCredentials").mockResolvedValue([ - {account: "testAcct", password: "testPassword"} - ]); - jest.spyOn(keytar, "deletePassword").mockResolvedValue(true); - const removeSyncSpy = jest.spyOn(fsExtra, "removeSync").mockImplementation(() => { - return true; - }); - - const handler = new ConvertProfilesHandler(); - jest.spyOn(handler as any, "getOldPluginInfo").mockReturnValueOnce({ plugins: [], overrides: [] }); - jest.spyOn(handler as any, "getOldProfileCount").mockReturnValueOnce(3); - const findOldSecurePropsSpy = jest.spyOn(handler as any, "findOldSecureProps"); - const deleteOldSecurePropsSpy = jest.spyOn(handler as any, "deleteOldSecureProps"); + expect(stdout).not.toContain("If you confirm the deletion of V1 profiles, they are deleted from disk"); + expect(stdout).not.toContain("after a successful conversion. Otherwise, they remain but no longer used."); + expect(stdout).not.toContain("You can also delete your V1 profiles later."); + expect(stdout).not.toContain("Do you want to delete your V1 profiles now [y/N]:"); - const params = getIHandlerParametersObject(); - params.arguments.prompt = false; - params.arguments.delete = true; - - await handler.process(params); - expect(stdout).toContain("Detected 3 old profile(s)"); - expect(stdout).toContain("Converted fruit profiles: apple, coconut, banana"); - expect(stdout).toContain("Deleting the profiles directory"); - expect(stdout).toContain("Deleting secure value for \"@brightside/core/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"@zowe/cli/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"Zowe-Plugin/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"Broadcom-Plugin/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"Zowe/testAcct\""); - expect(updateSchemaSpy).toHaveBeenCalled(); - expect(mockImperativeConfig.config.save).toHaveBeenCalled(); - expect(removeSyncSpy).toHaveBeenCalledTimes(1); - expect(findOldSecurePropsSpy).toHaveBeenCalledTimes(5); - expect(deleteOldSecurePropsSpy).toHaveBeenCalledTimes(5); + expect(stdout).toContain("Report Msg 1"); + expect(stdout).toContain("Report Msg 2"); + expect(stderr).toContain("Error Msg 1"); + expect(stderr).toContain("Error Msg 2"); }); - it("should remove existing profiles and delete secure properties with prompt", async () => { - const metaError = new Error("invalid meta file"); - jest.spyOn(ConfigBuilder, "convert").mockResolvedValueOnce({ - config: Config.empty(), - profilesConverted: { - fruit: ["apple", "coconut", "banana"] - }, - profilesFailed: [] - }); - const updateSchemaSpy = jest.spyOn(ConfigSchema, "updateSchema").mockReturnValueOnce(undefined); - jest.spyOn(fs, "renameSync").mockReturnValueOnce(); - jest.spyOn(keytar, "findCredentials").mockResolvedValue([ - {account: "testAcct", password: "testPassword"} - ]); - jest.spyOn(keytar, "deletePassword").mockResolvedValue(true); - const removeSyncSpy = jest.spyOn(fsExtra, "removeSync").mockImplementation(() => { - return true; - }); - - const handler = new ConvertProfilesHandler(); - jest.spyOn(handler as any, "getOldPluginInfo").mockReturnValueOnce({ plugins: [], overrides: [] }); - jest.spyOn(handler as any, "getOldProfileCount").mockReturnValueOnce(3); - const findOldSecurePropsSpy = jest.spyOn(handler as any, "findOldSecureProps"); - const deleteOldSecurePropsSpy = jest.spyOn(handler as any, "deleteOldSecureProps"); + it("should prompt for confirmation and delete profiles when requested", async () => { + // pretend that convert works + convertSpy = jest.spyOn(ConvertV1Profiles, "convert").mockResolvedValue(Promise.resolve(fakeConvertResult)); + // call the function that we want to test const params = getIHandlerParametersObject(); - (params.response.console.prompt as any).mockResolvedValueOnce("y").mockResolvedValueOnce("y"); params.arguments.delete = true; + params.arguments.prompt = true; + await convProfHandler.process(params); - await handler.process(params); - expect(stdout).toContain("Detected 3 old profile(s)"); - expect(stdout).toContain("Converted fruit profiles: apple, coconut, banana"); - expect(stdout).toContain("Deleting the profiles directory"); - expect(stdout).toContain("Deleting secure value for \"@brightside/core/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"@zowe/cli/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"Zowe-Plugin/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"Broadcom-Plugin/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"Zowe/testAcct\""); - expect(updateSchemaSpy).toHaveBeenCalled(); - expect(mockImperativeConfig.config.save).toHaveBeenCalled(); - expect(removeSyncSpy).toHaveBeenCalledTimes(1); - expect(findOldSecurePropsSpy).toHaveBeenCalledTimes(5); - expect(deleteOldSecurePropsSpy).toHaveBeenCalledTimes(5); - expect(params.response.console.prompt).toHaveBeenCalledTimes(2); - }); - - it("should remove existing profiles and not delete secure properties with prompt", async () => { - const metaError = new Error("invalid meta file"); - jest.spyOn(ConfigBuilder, "convert").mockResolvedValueOnce({ - config: Config.empty(), - profilesConverted: { - fruit: ["apple", "coconut", "banana"] - }, - profilesFailed: [] - }); - const updateSchemaSpy = jest.spyOn(ConfigSchema, "updateSchema").mockReturnValueOnce(undefined); - jest.spyOn(fs, "renameSync").mockReturnValueOnce(); - jest.spyOn(keytar, "findCredentials").mockResolvedValue([ - {account: "testAcct", password: "testPassword"} - ]); - jest.spyOn(keytar, "deletePassword").mockResolvedValue(true); - const removeSyncSpy = jest.spyOn(fsExtra, "removeSync").mockImplementation(() => { - return true; - }); - - const handler = new ConvertProfilesHandler(); - jest.spyOn(handler as any, "getOldPluginInfo").mockReturnValueOnce({ plugins: [], overrides: [] }); - jest.spyOn(handler as any, "getOldProfileCount").mockReturnValueOnce(3); - const findOldSecurePropsSpy = jest.spyOn(handler as any, "findOldSecureProps"); - const deleteOldSecurePropsSpy = jest.spyOn(handler as any, "deleteOldSecureProps"); + expect(stdout).toContain("If you confirm the deletion of V1 profiles, they are deleted from disk after"); + expect(stdout).toContain("a successful conversion. Otherwise, they remain but are no longer used."); + expect(stdout).toContain("You can also delete your V1 profiles later."); + expect(stdout).toContain("Do you want to delete your V1 profiles now [y/N]:"); - const params = getIHandlerParametersObject(); - (params.response.console.prompt as any).mockResolvedValueOnce("y").mockResolvedValueOnce("n"); - params.arguments.delete = true; + expect(convertSpy).toHaveBeenCalledWith({ deleteV1Profs: true }); - await handler.process(params); - expect(stdout).toContain("Detected 3 old profile(s)"); - expect(stdout).toContain("Converted fruit profiles: apple, coconut, banana"); - expect(stdout).not.toContain("Deleting the profiles directory"); - expect(stdout).not.toContain("Deleting secure value for \"@brightside/core/testAcct\""); - expect(stdout).not.toContain("Deleting secure value for \"@zowe/cli/testAcct\""); - expect(stdout).not.toContain("Deleting secure value for \"Zowe-Plugin/testAcct\""); - expect(stdout).not.toContain("Deleting secure value for \"Broadcom-Plugin/testAcct\""); - expect(stdout).not.toContain("Deleting secure value for \"Zowe/testAcct\""); - expect(updateSchemaSpy).toHaveBeenCalled(); - expect(mockImperativeConfig.config.save).toHaveBeenCalled(); - expect(removeSyncSpy).toHaveBeenCalledTimes(0); - expect(findOldSecurePropsSpy).toHaveBeenCalledTimes(0); - expect(deleteOldSecurePropsSpy).toHaveBeenCalledTimes(0); - expect(params.response.console.prompt).toHaveBeenCalledTimes(2); + expect(stdout).toContain("Report Msg 1"); + expect(stdout).toContain("Report Msg 2"); + expect(stderr).toContain("Error Msg 1"); + expect(stderr).toContain("Error Msg 2"); }); - it("should remove existing profiles and delete secure properties except secure_config_props", async () => { - const metaError = new Error("invalid meta file"); - jest.spyOn(ConfigBuilder, "convert").mockResolvedValueOnce({ - config: Config.empty(), - profilesConverted: { - fruit: ["apple", "coconut", "banana"] - }, - profilesFailed: [] - }); - const updateSchemaSpy = jest.spyOn(ConfigSchema, "updateSchema").mockReturnValueOnce(undefined); - jest.spyOn(fs, "renameSync").mockReturnValueOnce(); - jest.spyOn(keytar, "findCredentials").mockResolvedValue([ - {account: "testAcct", password: "testPassword"}, - {account: "secure_config_props", password: "testPassword"}, - {account: "secure_config_props-1", password: "testPassword"} - ]); - jest.spyOn(keytar, "deletePassword").mockResolvedValue(true); - const removeSyncSpy = jest.spyOn(fsExtra, "removeSync").mockImplementation(() => { - return true; - }); - - const handler = new ConvertProfilesHandler(); - jest.spyOn(handler as any, "getOldPluginInfo").mockReturnValueOnce({ plugins: [], overrides: [] }); - jest.spyOn(handler as any, "getOldProfileCount").mockReturnValueOnce(3); - const findOldSecurePropsSpy = jest.spyOn(handler as any, "findOldSecureProps"); - const deleteOldSecurePropsSpy = jest.spyOn(handler as any, "deleteOldSecureProps"); + it("should not delete profiles when answer to prompt is to not delete", async () => { + // pretend that convert works + convertSpy = jest.spyOn(ConvertV1Profiles, "convert").mockResolvedValue(Promise.resolve(fakeConvertResult)); + // pretend that the user answers no when prompted const params = getIHandlerParametersObject(); - params.arguments.prompt = false; params.arguments.delete = true; - - await handler.process(params); - expect(stdout).toContain("Detected 3 old profile(s)"); - expect(stdout).toContain("Converted fruit profiles: apple, coconut, banana"); - expect(stdout).toContain("Deleting the profiles directory"); - expect(stdout).toContain("Deleting secure value for \"@brightside/core/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"@zowe/cli/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"Zowe-Plugin/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"Broadcom-Plugin/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"Zowe/testAcct\""); - expect(updateSchemaSpy).toHaveBeenCalled(); - expect(mockImperativeConfig.config.save).toHaveBeenCalled(); - expect(removeSyncSpy).toHaveBeenCalledTimes(1); - expect(findOldSecurePropsSpy).toHaveBeenCalledTimes(5); - expect(deleteOldSecurePropsSpy).toHaveBeenCalledTimes(5); - }); - - it("should handle no profiles and delete secure properties except secure_config_props with prompt", async () => { - const configBuilderConvertSpy = jest.spyOn(ConfigBuilder, "convert").mockResolvedValueOnce({ - config: Config.empty(), - profilesConverted: {}, - profilesFailed: [] - }); - const updateSchemaSpy = jest.spyOn(ConfigSchema, "updateSchema").mockReturnValueOnce(undefined); - jest.spyOn(fs, "renameSync").mockReturnValueOnce(); - jest.spyOn(keytar, "findCredentials").mockResolvedValue([ - {account: "testAcct", password: "testPassword"}, - {account: "secure_config_props", password: "testPassword"}, - {account: "secure_config_props-1", password: "testPassword"} - ]); - jest.spyOn(keytar, "deletePassword").mockResolvedValue(true); - const removeSyncSpy = jest.spyOn(fsExtra, "removeSync").mockImplementation(() => { - return true; - }); - - const handler = new ConvertProfilesHandler(); - jest.spyOn(handler as any, "getOldPluginInfo").mockReturnValueOnce({ plugins: [], overrides: [] }); - jest.spyOn(handler as any, "getOldProfileCount").mockReturnValueOnce(0); - const findOldSecurePropsSpy = jest.spyOn(handler as any, "findOldSecureProps"); - const deleteOldSecurePropsSpy = jest.spyOn(handler as any, "deleteOldSecureProps"); - - const params = getIHandlerParametersObject(); - (params.response.console.prompt as any).mockResolvedValueOnce("y"); params.arguments.prompt = true; - params.arguments.delete = true; + params.response.console.prompt = jest.fn((promptString) => { + stdout += promptString; + return "n"; + }) as any; - await handler.process(params); - expect(stdout).toContain("No old profiles were found"); - expect(stdout).toContain("Deleting the profiles directory"); - expect(stdout).toContain("Deleting secure value for \"@brightside/core/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"@zowe/cli/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"Zowe-Plugin/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"Broadcom-Plugin/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"Zowe/testAcct\""); - expect(configBuilderConvertSpy).not.toHaveBeenCalled(); - expect(updateSchemaSpy).not.toHaveBeenCalled(); - expect(mockImperativeConfig.config.save).not.toHaveBeenCalled(); - expect(removeSyncSpy).toHaveBeenCalledTimes(1); - expect(findOldSecurePropsSpy).toHaveBeenCalledTimes(5); - expect(deleteOldSecurePropsSpy).toHaveBeenCalledTimes(5); - expect(params.response.console.prompt).toHaveBeenCalledTimes(1); - }); - - it("should remove existing profiles, delete secure properties, and handle a rimraf delete error", async () => { - jest.spyOn(ConfigBuilder, "convert").mockResolvedValueOnce({ - config: Config.empty(), - profilesConverted: { - fruit: ["apple", "coconut", "banana"] - }, - profilesFailed: [] - }); - const updateSchemaSpy = jest.spyOn(ConfigSchema, "updateSchema").mockReturnValueOnce(undefined); - jest.spyOn(fs, "renameSync").mockReturnValueOnce(); - jest.spyOn(keytar, "findCredentials").mockResolvedValue([ - {account: "testAcct", password: "testPassword"} - ]); - jest.spyOn(keytar, "deletePassword").mockResolvedValue(true); - const removeSyncSpy = jest.spyOn(fsExtra, "removeSync").mockImplementation(() => { - throw new Error("test error"); - }); + // call the function that we want to test + await convProfHandler.process(params); - const handler = new ConvertProfilesHandler(); - jest.spyOn(handler as any, "getOldPluginInfo").mockReturnValueOnce({ plugins: [], overrides: [] }); - jest.spyOn(handler as any, "getOldProfileCount").mockReturnValueOnce(3); - const findOldSecurePropsSpy = jest.spyOn(handler as any, "findOldSecureProps"); - const deleteOldSecurePropsSpy = jest.spyOn(handler as any, "deleteOldSecureProps"); + expect(stdout).toContain("If you confirm the deletion of V1 profiles, they are deleted from disk after"); + expect(stdout).toContain("a successful conversion. Otherwise, they remain but are no longer used."); + expect(stdout).toContain("You can also delete your V1 profiles later."); + expect(stdout).toContain("Do you want to delete your V1 profiles now [y/N]:"); - const params = getIHandlerParametersObject(); - params.arguments.prompt = false; - params.arguments.delete = true; + expect(convertSpy).toHaveBeenCalledWith({ deleteV1Profs: false }); - await handler.process(params); - expect(stdout).toContain("Detected 3 old profile(s)"); - expect(stdout).toContain("Converted fruit profiles: apple, coconut, banana"); - expect(stdout).toContain("Deleting secure value for \"@brightside/core/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"@zowe/cli/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"Zowe-Plugin/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"Broadcom-Plugin/testAcct\""); - expect(stdout).toContain("Deleting secure value for \"Zowe/testAcct\""); - expect(stderr).toContain("Failed to delete the profiles directory"); - expect(updateSchemaSpy).toHaveBeenCalled(); - expect(mockImperativeConfig.config.save).toHaveBeenCalled(); - expect(removeSyncSpy).toHaveBeenCalledTimes(1); - expect(findOldSecurePropsSpy).toHaveBeenCalledTimes(5); - expect(deleteOldSecurePropsSpy).toHaveBeenCalledTimes(5); + expect(stdout).toContain("Report Msg 1"); + expect(stdout).toContain("Report Msg 2"); + expect(stderr).toContain("Error Msg 1"); + expect(stderr).toContain("Error Msg 2"); }); - it("should throw an error if keytar unavailable", async () => { - const metaError = new Error("invalid meta file"); - jest.spyOn(ConfigBuilder, "convert").mockResolvedValueOnce({ - config: Config.empty(), - profilesConverted: { - fruit: ["apple", "coconut", "banana"] - }, - profilesFailed: [] - }); - const updateSchemaSpy = jest.spyOn(ConfigSchema, "updateSchema").mockReturnValueOnce(undefined); - jest.spyOn(fs, "renameSync").mockReturnValueOnce(); - jest.spyOn(keytar, "findCredentials").mockImplementation(() => { - throw new Error("test error"); - }); - const removeSyncSpy = jest.spyOn(fsExtra, "removeSync").mockImplementation(() => { - return true; - }); + it("should report any discovered old SCS plugin and uninstall it", async () => { + // pretend convert reported an SCS plugin + fakeConvertResult.v1ScsPluginName = "fakeScsPluginName" as any; + convertSpy = jest.spyOn(ConvertV1Profiles, "convert").mockResolvedValue(Promise.resolve(fakeConvertResult)); - const handler = new ConvertProfilesHandler(); - jest.spyOn(handler as any, "getOldPluginInfo").mockReturnValueOnce({ plugins: [], overrides: [] }); - jest.spyOn(handler as any, "getOldProfileCount").mockReturnValueOnce(3); + // avoid calling the real plugin uninstall + const uninstallPlugin = require("../../../../src/plugins/utilities/npm-interface/uninstall"); + const uninstallSpy = jest.spyOn(uninstallPlugin, "uninstall").mockReturnValue(0); + // call the function that we want to test const params = getIHandlerParametersObject(); - params.arguments.prompt = false; - params.arguments.delete = true; - - await handler.process(params); - expect(stdout).toContain("Detected 3 old profile(s)"); - expect(stdout).toContain("Converted fruit profiles: apple, coconut, banana"); - expect(stdout).toContain("Deleting the profiles directory"); - expect(stderr).toContain("Keytar or the credential vault are unavailable."); - expect(stdout).not.toContain("Deleting secure value for \"@brightside/core/testAcct\""); - expect(stdout).not.toContain("Deleting secure value for \"@zowe/cli/testAcct\""); - expect(stdout).not.toContain("Deleting secure value for \"Zowe-Plugin/testAcct\""); - expect(stdout).not.toContain("Deleting secure value for \"Broadcom-Plugin/testAcct\""); - expect(stdout).not.toContain("Deleting secure value for \"Zowe/testAcct\""); - expect(updateSchemaSpy).toHaveBeenCalled(); - expect(mockImperativeConfig.config.save).toHaveBeenCalled(); - expect(removeSyncSpy).toHaveBeenCalledTimes(1); - }); - - describe("getOldPluginInfo", () => { - it("should return empty list", () => { - const handler = new ConvertProfilesHandler(); - mockImperativeConfig.hostPackageName = "fake-cli"; - const result = (handler as any).getOldPluginInfo(); - expect(result).toMatchObject({ plugins: [], overrides: [] }); - }); + await convProfHandler.process(params); - it("should return default credential manager with override for Zowe CLI v1", () => { - mockImperativeConfig.hostPackageName = "@zowe/cli"; - const pluginName = "@zowe/secure-credential-store-for-zowe-cli"; - jest.spyOn(AppSettings, "instance", "get").mockReturnValue({ - get: jest.fn().mockReturnValue(pluginName) - } as any); - jest.spyOn(PluginIssues, "instance", "get").mockReturnValue({ - getInstalledPlugins: jest.fn().mockReturnValue({ [pluginName]: null }) - } as any); - - const handler = new ConvertProfilesHandler(); - const result = (handler as any).getOldPluginInfo(); - expect(result).toMatchObject({ - plugins: [pluginName], - overrides: ["CredentialManager"] - }); - }); - - it("should return default credential manager without override for Zowe CLI v1", () => { - mockImperativeConfig.hostPackageName = "@zowe/cli"; - const pluginName = "@zowe/secure-credential-store-for-zowe-cli"; - jest.spyOn(AppSettings, "instance", "get").mockReturnValue({ - get: jest.fn().mockReturnValue(false) - } as any); - jest.spyOn(PluginIssues, "instance", "get").mockReturnValue({ - getInstalledPlugins: jest.fn().mockReturnValue({ [pluginName]: null }) - } as any); - - const handler = new ConvertProfilesHandler(); - const result = (handler as any).getOldPluginInfo(); - expect(result).toMatchObject({ - plugins: [pluginName], - overrides: [] - }); - }); - - it("should return old credential manager plug-in for Zowe CLI v2", () => { - mockImperativeConfig.hostPackageName = "@zowe/cli"; - const pluginName = "@zowe/secure-credential-store-for-zowe-cli"; - jest.spyOn(AppSettings, "instance", "get").mockReturnValue({ - get: jest.fn().mockReturnValue("@zowe/cli") - } as any); - jest.spyOn(PluginIssues, "instance", "get").mockReturnValue({ - getInstalledPlugins: jest.fn().mockReturnValue({ [pluginName]: null }) - } as any); - - const handler = new ConvertProfilesHandler(); - const result = (handler as any).getOldPluginInfo(); - expect(result).toMatchObject({ - plugins: [pluginName], - overrides: [] - }); - }); - - it("should not return default credential manager for Zowe CLI v2", () => { - mockImperativeConfig.hostPackageName = "@zowe/cli"; - jest.spyOn(AppSettings, "instance", "get").mockReturnValue({ - get: jest.fn().mockReturnValue("@zowe/cli") - } as any); - jest.spyOn(PluginIssues, "instance", "get").mockReturnValue({ - getInstalledPlugins: jest.fn().mockReturnValue({}) - } as any); - - const handler = new ConvertProfilesHandler(); - const result = (handler as any).getOldPluginInfo(); - expect(result).toMatchObject({ plugins: [], overrides: [] }); - }); - - it("should return custom credential manager override for Zowe CLI", () => { - mockImperativeConfig.hostPackageName = "@zowe/cli"; - jest.spyOn(AppSettings, "instance", "get").mockReturnValue({ - get: jest.fn().mockReturnValue("ABC") - } as any); - jest.spyOn(PluginIssues, "instance", "get").mockReturnValue({ - getInstalledPlugins: jest.fn().mockReturnValue({}) - } as any); - - const handler = new ConvertProfilesHandler(); - const result = (handler as any).getOldPluginInfo(); - expect(result).toMatchObject({ - plugins: [], - overrides: ["CredentialManager"] - }); - }); - }); - - describe("checkKeytarAvailable", () => { - it("should return true if keytar does not error out", async () => { - const findCredentialsSpy = jest.spyOn(keytar, "findCredentials").mockResolvedValue([{account: "fake", password: "fake"}]); - - const handler = new ConvertProfilesHandler(); - const result = await (handler as any).checkKeytarAvailable(); - expect(result).toEqual(true); - expect(findCredentialsSpy).toHaveBeenCalledWith("@zowe/cli"); - }); - it("should return false if keytar errors out", async () => { - jest.spyOn(keytar, "findCredentials").mockImplementation(() => { - throw new Error("fake error"); - }); - - const handler = new ConvertProfilesHandler(); - const result = await (handler as any).checkKeytarAvailable(); - expect(result).toEqual(false); - }); - }); - - describe("findOldSecureProps", () => { - it("should find existing Zowe accounts", async () => { - const findCredentialsSpy = jest.spyOn(keytar, "findCredentials").mockResolvedValue([ - {account: "fake1", password: "fakePass1"}, - {account: "fake2", password: "fakePass2"}, - {account: "fake3", password: "fakePass3"}, - {account: "fake4", password: "fakePass4"} - ]); - - const handler = new ConvertProfilesHandler(); - Object.defineProperty(handler, "keytar", {writable: false, value: keytar}); - const handlerParmsObj = getIHandlerParametersObject(); - const result = await (handler as any).findOldSecureProps("Zowe", handlerParmsObj); - expect(result).toEqual(["fake1", "fake2", "fake3", "fake4"]); - expect(findCredentialsSpy).toHaveBeenCalledWith("Zowe"); - expect(handlerParmsObj.response.console.error).toHaveBeenCalledTimes(0); - }); - it("should not find existing Zowe accounts", async () => { - const findCredentialsSpy = jest.spyOn(keytar, "findCredentials").mockResolvedValue([]); - - const handler = new ConvertProfilesHandler(); - Object.defineProperty(handler, "keytar", {writable: false, value: keytar}); - const handlerParmsObj = getIHandlerParametersObject(); - const result = await (handler as any).findOldSecureProps("Zowe", handlerParmsObj); - expect(result).toEqual([]); - expect(findCredentialsSpy).toHaveBeenCalledWith("Zowe"); - expect(handlerParmsObj.response.console.error).toHaveBeenCalledTimes(0); - }); - it("should error while finding existing Zowe accounts and catch error", async () => { - const findCredentialsSpy = jest.spyOn(keytar, "findCredentials").mockImplementation(() => { - throw new Error("test error"); - }); - - const handler = new ConvertProfilesHandler(); - Object.defineProperty(handler, "keytar", {writable: false, value: keytar}); - const handlerParmsObj = getIHandlerParametersObject(); - const result = await (handler as any).findOldSecureProps("Zowe", handlerParmsObj); - expect(result).toEqual([]); - expect(findCredentialsSpy).toHaveBeenCalledWith("Zowe"); - expect(handlerParmsObj.response.console.error).toHaveBeenCalledTimes(1); - expect(stderr).toContain("Encountered an error while gathering profiles for service"); - }); + expect(uninstallSpy).toHaveBeenCalled(); + expect(stdout).toContain("Report Msg 1"); + expect(stdout).toContain("Report Msg 2"); + expect(stdout).toContain('Successfully uninstalled plug-in fakeScsPluginName'); + expect(stderr).toContain("Error Msg 1"); + expect(stderr).toContain("Error Msg 2"); }); - describe("deleteOldSecureProps", () => { - it("should properly delete a credential and return success", async() => { - const findCredentialsSpy = jest.spyOn(keytar, "deletePassword").mockResolvedValue(true); - - const handler = new ConvertProfilesHandler(); - Object.defineProperty(handler, "keytar", {writable: false, value: keytar}); - const handlerParmsObj = getIHandlerParametersObject(); - const result = await (handler as any).deleteOldSecureProps("Zowe", "zosmf_test_user", handlerParmsObj); - expect(result).toEqual(true); - expect(findCredentialsSpy).toHaveBeenCalledWith("Zowe", "zosmf_test_user"); - expect(handlerParmsObj.response.console.error).toHaveBeenCalledTimes(0); - }); - it("should not properly delete a credential and return failure", async() => { - const findCredentialsSpy = jest.spyOn(keytar, "deletePassword").mockResolvedValue(false); - - const handler = new ConvertProfilesHandler(); - Object.defineProperty(handler, "keytar", {writable: false, value: keytar}); - const handlerParmsObj = getIHandlerParametersObject(); - const result = await (handler as any).deleteOldSecureProps("Zowe", "zosmf_test_user", handlerParmsObj); - expect(result).toEqual(false); - expect(findCredentialsSpy).toHaveBeenCalledWith("Zowe", "zosmf_test_user"); - expect(handlerParmsObj.response.console.error).toHaveBeenCalledTimes(0); - }); - it("should error while deleting a credential and return failure", async() => { - const findCredentialsSpy = jest.spyOn(keytar, "deletePassword").mockImplementation(() => { - throw new Error("test error"); - }); + it("should catch an error from uninstalling an old SCS plugin and report it", async () => { + // pretend convert reported an SCS plugin + fakeConvertResult.v1ScsPluginName = "fakeScsPluginName" as any; + convertSpy = jest.spyOn(ConvertV1Profiles, "convert").mockResolvedValue(Promise.resolve(fakeConvertResult)); - const handler = new ConvertProfilesHandler(); - Object.defineProperty(handler, "keytar", {writable: false, value: keytar}); - const handlerParmsObj = getIHandlerParametersObject(); - const result = await (handler as any).deleteOldSecureProps("Zowe", "zosmf_test_user", handlerParmsObj); - expect(result).toEqual(false); - expect(findCredentialsSpy).toHaveBeenCalledWith("Zowe", "zosmf_test_user"); - expect(handlerParmsObj.response.console.error).toHaveBeenCalledTimes(1); - expect(stderr).toContain("Encountered an error while deleting secure data for service"); + // pretend that plugin uninstall crashes + const fakeUninstallErr = "Plugin uninstall crashed and burned"; + const uninstallPlugin = require("../../../../src/plugins/utilities/npm-interface/uninstall"); + const uninstallSpy = jest.spyOn(uninstallPlugin, "uninstall").mockImplementation(() => { + throw new Error(fakeUninstallErr); }); - }); - - it("getOldProfileCount should find multiple types of profiles", () => { - jest.spyOn(ProfileIO, "getAllProfileDirectories").mockReturnValueOnce(["fruit", "nut"]); - jest.spyOn(ProfileIO, "getAllProfileNames") - .mockReturnValueOnce(["apple", "banana", "coconut"]) - .mockReturnValueOnce(["almond", "brazil", "cashew"]); - - const handler = new ConvertProfilesHandler(); - const result = (handler as any).getOldProfileCount(__dirname); - expect(result).toBe(6); - }); - it("removeOverride should reset CredentialManager override", () => { - const mockSetOverride = jest.fn(); - jest.spyOn(AppSettings, "instance", "get").mockReturnValue({ - set: mockSetOverride - } as any); - mockImperativeConfig.hostPackageName = "fake-cli"; - mockImperativeConfig.loadedConfig = { - overrides: { - CredentialManager: "ABC" - } - }; + // call the function that we want to test + const params = getIHandlerParametersObject(); + await convProfHandler.process(params); - const handler = new ConvertProfilesHandler(); - (handler as any).removeOverride("CredentialManager"); - expect(mockSetOverride).toHaveBeenCalledWith("overrides", "CredentialManager", "fake-cli"); - expect(mockImperativeConfig.loadedConfig.overrides.CredentialManager).toBeUndefined(); + expect(uninstallSpy).toHaveBeenCalled(); + expect(stdout).toContain("Report Msg 1"); + expect(stdout).toContain("Report Msg 2"); + expect(stderr).toContain("Error Msg 1"); + expect(stderr).toContain("Error Msg 2"); + expect(stderr).toContain('Failed to uninstall plug-in fakeScsPluginName'); + expect(stderr).toContain(fakeUninstallErr); }); }); diff --git a/packages/imperative/src/imperative/__tests__/config/cmd/edit/edit.handler.unit.test.ts b/packages/imperative/src/imperative/__tests__/config/cmd/edit/edit.handler.unit.test.ts index 702e1be20d..1a137dc806 100644 --- a/packages/imperative/src/imperative/__tests__/config/cmd/edit/edit.handler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/config/cmd/edit/edit.handler.unit.test.ts @@ -82,6 +82,6 @@ describe("Configuration Edit command handler", () => { const params = getIHandlerParametersObject(); await handler.process(params); - expect(editFileSpy).toHaveBeenCalledWith("fake"); + expect(editFileSpy).toHaveBeenCalledWith("fake", undefined); }); }); diff --git a/packages/imperative/src/imperative/__tests__/config/cmd/import/import.handler.unit.test.ts b/packages/imperative/src/imperative/__tests__/config/cmd/import/import.handler.unit.test.ts index 96b0e17491..2d4af8c553 100644 --- a/packages/imperative/src/imperative/__tests__/config/cmd/import/import.handler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/config/cmd/import/import.handler.unit.test.ts @@ -19,14 +19,13 @@ import { IHandlerParameters } from "../../../../../cmd"; import { Config, ConfigConstants, IConfig } from "../../../../../config"; import { ISession, RestClient } from "../../../../../rest"; import { ImperativeConfig } from "../../../../.."; -import { expectedConfigObject, expectedSchemaObject } from +import { expectedProjectConfigObject, expectedSchemaObject } from "../../../../../../__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/expectedObjects"; -import { NextVerFeatures } from "../../../../../utilities"; jest.mock("fs"); -const expectedConfigText = JSONC.stringify(expectedConfigObject, null, ConfigConstants.INDENT); -const expectedConfigObjectWithoutSchema = lodash.omit(expectedConfigObject, "$schema"); +const expectedConfigText = JSONC.stringify(expectedProjectConfigObject, null, ConfigConstants.INDENT); +const expectedConfigObjectWithoutSchema = lodash.omit(expectedProjectConfigObject, "$schema"); const expectedConfigTextWithoutSchema = JSONC.stringify(expectedConfigObjectWithoutSchema, null, ConfigConstants.INDENT); const expectedSchemaText = JSONC.stringify(expectedSchemaObject, null, ConfigConstants.INDENT); @@ -60,12 +59,6 @@ const getIHandlerParametersObject = (): IHandlerParameters => { }; describe("Configuration Import command handler", () => { - beforeEach(() => { - /* This avoids having to mock ImperativeConfig.envVariablePrefix. - * Unless overridden, tests will use our legacy format for errors. - */ - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(false); - }); describe("handler", () => { const readFileSyncSpy = jest.spyOn(fs, "readFileSync"); @@ -141,7 +134,7 @@ describe("Configuration Import command handler", () => { it("should import config with schema from web address", async () => { jest.spyOn(fs, "existsSync").mockReturnValueOnce(false); writeFileSyncSpy.mockReturnValueOnce(); - fetchConfigSpy.mockResolvedValueOnce(expectedConfigObject); + fetchConfigSpy.mockResolvedValueOnce(expectedProjectConfigObject); const params: IHandlerParameters = getIHandlerParametersObject(); params.arguments.location = "http://example.com/downloads/fakeapp.config.json"; @@ -206,7 +199,7 @@ describe("Configuration Import command handler", () => { expect(config.profiles).toBeDefined(); expect(config.defaults).toBeDefined(); - expect(config).toMatchObject(expectedConfigObject); + expect(config).toMatchObject(expectedProjectConfigObject); }); it("should throw error when config file is not valid JSON", async () => { diff --git a/packages/imperative/src/imperative/__tests__/config/cmd/init/init.handler.unit.test.ts b/packages/imperative/src/imperative/__tests__/config/cmd/init/init.handler.unit.test.ts index df45527c1c..5a337c38ec 100644 --- a/packages/imperative/src/imperative/__tests__/config/cmd/init/init.handler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/config/cmd/init/init.handler.unit.test.ts @@ -24,6 +24,7 @@ import * as fs from "fs"; import { CredentialManagerFactory } from "../../../../../security"; import { setupConfigToLoad } from "../../../../../../__tests__/src/TestUtil"; import { OverridesLoader } from "../../../../src/OverridesLoader"; +import { ConfigUtils, ImperativeError } from "../../../../.."; jest.mock("fs"); @@ -54,7 +55,10 @@ const getIHandlerParametersObject = (): IHandlerParameters => { }; const fakeConfig = config as IImperativeConfig; -fakeConfig.profiles.push(fakeConfig.baseProfile); // Add base profile to profiles array to mimic Imperative init +if (fakeConfig.profiles && fakeConfig.baseProfile) { + // Add base profile to profiles array to mimic Imperative init + fakeConfig.profiles.push(fakeConfig.baseProfile); +} const fakeProjPath = path.join(__dirname, "fakeapp.config.json"); const fakeSchemaPath = path.join(__dirname, "fakeapp.schema.json"); const fakeProjUserPath = path.join(__dirname, "fakeapp.config.user.json"); @@ -117,6 +121,13 @@ describe("Configuration Initialization command handler", () => { // Run tests for all the config layers testLayers.forEach(({ name, user, global, configPath, schemaPath }) => describe(`${name} layer`, () => { + let baseProfName: string; + if (global) { + baseProfName = "global_base"; + } else { + baseProfName = "project_base"; + } + it("should attempt to initialize the configuration", async () => { const handler = new InitHandler(); const params = getIHandlerParametersObject(); @@ -135,24 +146,24 @@ describe("Configuration Initialization command handler", () => { searchSpy.mockClear(); // initWithSchema - const promptWithTimeoutSpy = jest.fn(() => "fakeValue"); - (params.response.console as any).prompt = promptWithTimeoutSpy; + const readPromptSpy = jest.fn(() => "fakeValue"); + (params.response.console as any).prompt = readPromptSpy; writeFileSyncSpy.mockImplementation(); // Don't actually write files - if (!global) jest.spyOn(process, "cwd").mockReturnValueOnce(null); + if (!global) jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); await handler.process(params as IHandlerParameters); const compObj: any = { $schema: "./fakeapp.schema.json" }; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - if (!user) delete compObj.profiles.base.properties.secret; // Delete the secret + if (!user) delete compObj.profiles[baseProfName].properties.secret; // Delete the secret expect(ensureCredMgrSpy).toHaveBeenCalledTimes(1); expect(setSchemaSpy).toHaveBeenCalledTimes(1); expect(setSchemaSpy).toHaveBeenCalledWith(expectedSchemaObject); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(user ? 0 : 1); // User config is a skeleton - no prompting should occur + expect(readPromptSpy).toHaveBeenCalledTimes(user ? 0 : 1); // User config is a skeleton - no prompting should occur // Prompting for secure property - if (!user) expect(promptWithTimeoutSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); + if (!user) expect(readPromptSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); expect(editFileSpy).not.toHaveBeenCalled(); expect(writeFileSyncSpy).toHaveBeenCalledTimes(2); @@ -161,7 +172,7 @@ describe("Configuration Initialization command handler", () => { expect(writeFileSyncSpy).toHaveBeenNthCalledWith(2, configPath, JSON.stringify(compObj, null, ConfigConstants.INDENT)); // Secure value supplied during prompting should be on properties - if (!user) expect(ImperativeConfig.instance.config.properties.profiles.base.properties.secret).toEqual("fakeValue"); + if (!user) expect(ImperativeConfig.instance.config.properties.profiles[baseProfName].properties.secret).toEqual("fakeValue"); }); it("should attempt to do a dry run of initializing the configuration", async () => { @@ -183,22 +194,24 @@ describe("Configuration Initialization command handler", () => { searchSpy.mockClear(); // initWithSchema - const promptWithTimeoutSpy = jest.fn(() => "fakeValue"); - (params.response.console as any).prompt = promptWithTimeoutSpy; + const readPromptSpy = jest.fn(() => "fakeValue"); + (params.response.console as any).prompt = readPromptSpy; writeFileSyncSpy.mockImplementation(); // Don't actually write files // initForDryRun const initForDryRunSpy = jest.spyOn(handler as any, "initForDryRun"); - if (!global) jest.spyOn(process, "cwd").mockReturnValueOnce(null); + if (!global) jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); await handler.process(params as IHandlerParameters); expect(ensureCredMgrSpy).toHaveBeenCalledTimes(1); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(0); // Dry run mode - no prompting should occur + expect(readPromptSpy).toHaveBeenCalledTimes(0); // Dry run mode - no prompting should occur expect(initForDryRunSpy).toHaveBeenCalledTimes(1); - expect(initForDryRunSpy).toHaveBeenCalledWith(ImperativeConfig.instance.config, params.arguments.userConfig); + expect(initForDryRunSpy).toHaveBeenCalledWith(ImperativeConfig.instance.config, + params.arguments.userConfig, params.arguments.globalConfig + ); expect(writeFileSyncSpy).not.toHaveBeenCalled(); }); @@ -224,34 +237,34 @@ describe("Configuration Initialization command handler", () => { searchSpy.mockClear(); // initWithSchema - const promptWithTimeoutSpy = jest.fn(() => "fakeValue"); - (params.response.console as any).prompt = promptWithTimeoutSpy; + const readPromptSpy = jest.fn(() => "fakeValue"); + (params.response.console as any).prompt = readPromptSpy; writeFileSyncSpy.mockImplementation(); // Don't actually write files - if (!global) jest.spyOn(process, "cwd").mockReturnValueOnce(null); + if (!global) jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); await handler.process(params as IHandlerParameters); const compObj: any = { $schema: "./fakeapp.schema.json" }; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - if (!user) delete compObj.profiles.base.properties.secret; // Delete the secret + if (!user) delete compObj.profiles[baseProfName].properties.secret; // Delete the secret expect(ensureCredMgrSpy).toHaveBeenCalledTimes(1); expect(setSchemaSpy).toHaveBeenCalledTimes(1); expect(setSchemaSpy).toHaveBeenCalledWith(expectedSchemaObject); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(user ? 0 : 1); + expect(readPromptSpy).toHaveBeenCalledTimes(user ? 0 : 1); // Prompting for secure property - if (!user) expect(promptWithTimeoutSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); + if (!user) expect(readPromptSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); expect(writeFileSyncSpy).toHaveBeenCalledTimes(2); // Secure value supplied during prompting should be on properties - if (!user) expect(ImperativeConfig.instance.config.properties.profiles.base.properties.secret).toEqual("fakeValue"); + if (!user) expect(ImperativeConfig.instance.config.properties.profiles[baseProfName].properties.secret).toEqual("fakeValue"); // initWithSchema called with the correct parameters expect(initWithSchemaSpy).toHaveBeenCalledTimes(1); expect(initWithSchemaSpy).toHaveBeenCalledWith(ImperativeConfig.instance.config, params.arguments.userConfig, - params.arguments.overwrite && params.arguments.forSure); + params.arguments.globalConfig, params.arguments.overwrite && params.arguments.forSure); }); it("should attempt to initialize the configuration with prompting disabled", async () => { @@ -272,11 +285,11 @@ describe("Configuration Initialization command handler", () => { searchSpy.mockClear(); // initWithSchema - const promptWithTimeoutSpy = jest.fn(() => "fakeValue"); - (params.response.console as any).prompt = promptWithTimeoutSpy; + const readPromptSpy = jest.fn(() => "fakeValue"); + (params.response.console as any).prompt = readPromptSpy; writeFileSyncSpy.mockImplementation(); // Don't actually write files - if (!global) jest.spyOn(process, "cwd").mockReturnValueOnce(null); + if (!global) jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); await handler.process(params as IHandlerParameters); const compObj: any = { $schema: "./fakeapp.schema.json" }; // Fill in the name of the schema file, and make it first @@ -285,7 +298,7 @@ describe("Configuration Initialization command handler", () => { expect(setSchemaSpy).toHaveBeenCalledTimes(1); expect(setSchemaSpy).toHaveBeenCalledWith(expectedSchemaObject); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(0); // CI flag should not prompt + expect(readPromptSpy).toHaveBeenCalledTimes(0); // CI flag should not prompt expect(writeFileSyncSpy).toHaveBeenCalledTimes(2); // 1 = Schema and 2 = Config @@ -314,11 +327,11 @@ describe("Configuration Initialization command handler", () => { searchSpy.mockClear(); // initWithSchema - const promptWithTimeoutSpy = jest.fn(() => "fakeValue"); - (params.response.console as any).prompt = promptWithTimeoutSpy; + const readPromptSpy = jest.fn(() => "fakeValue"); + (params.response.console as any).prompt = readPromptSpy; writeFileSyncSpy.mockImplementation(); // Don't actually write files - if (!global) jest.spyOn(process, "cwd").mockReturnValueOnce(null); + if (!global) jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); await handler.process(params as IHandlerParameters); const compObj: any = { $schema: "./fakeapp.schema.json" }; // Fill in the name of the schema file, and make it first @@ -327,14 +340,14 @@ describe("Configuration Initialization command handler", () => { expect(setSchemaSpy).toHaveBeenCalledTimes(1); expect(setSchemaSpy).toHaveBeenCalledWith(expectedSchemaObject); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(0); // CI flag should not prompt + expect(readPromptSpy).toHaveBeenCalledTimes(0); // CI flag should not prompt expect(writeFileSyncSpy).toHaveBeenCalledTimes(2); // initWithSchema called with the correct parameters expect(initWithSchemaSpy).toHaveBeenCalledTimes(1); expect(initWithSchemaSpy).toHaveBeenCalledWith(ImperativeConfig.instance.config, params.arguments.userConfig, - params.arguments.overwrite && params.arguments.forSure); + params.arguments.globalConfig, params.arguments.overwrite && params.arguments.forSure); }); it("should attempt to do a dry run of initializing the configuration and handle no changes", async () => { @@ -353,11 +366,11 @@ describe("Configuration Initialization command handler", () => { searchSpy.mockClear(); // initWithSchema - const promptWithTimeoutSpy = jest.fn(() => "fakeValue"); - (params.response.console as any).prompt = promptWithTimeoutSpy; + const readPromptSpy = jest.fn(() => "fakeValue"); + (params.response.console as any).prompt = readPromptSpy; writeFileSyncSpy.mockImplementation(); // Don't actually write files - if (!global) jest.spyOn(process, "cwd").mockReturnValueOnce(null); + if (!global) jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); await handler.process(params as IHandlerParameters); const compObj: any = { $schema: "./fakeapp.schema.json" }; // Fill in the name of the schema file, and make it first @@ -369,11 +382,13 @@ describe("Configuration Initialization command handler", () => { const jsonDataSpy = jest.spyOn(params.response.data, "setObj"); params.arguments.dryRun = true; - if (!global) jest.spyOn(process, "cwd").mockReturnValueOnce(null); + if (!global) jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); await handler.process(params as IHandlerParameters); expect(initForDryRunSpy).toHaveBeenCalledTimes(1); - expect(initForDryRunSpy).toHaveBeenCalledWith(ImperativeConfig.instance.config, params.arguments.userConfig); + expect(initForDryRunSpy).toHaveBeenCalledWith(ImperativeConfig.instance.config, + params.arguments.userConfig, params.arguments.globalConfig + ); expect(jsonDataSpy).toHaveBeenCalledTimes(1); // console.log(jsonDataSpy.mock.calls[0][0]); @@ -399,20 +414,20 @@ describe("Configuration Initialization command handler", () => { searchSpy.mockClear(); // initWithSchema - const promptWithTimeoutSpy = jest.fn(() => "fakeValue"); - (params.response.console as any).prompt = promptWithTimeoutSpy; + const readPromptSpy = jest.fn(() => "fakeValue"); + (params.response.console as any).prompt = readPromptSpy; writeFileSyncSpy.mockImplementation(); // Don't actually write files - if (!global) jest.spyOn(process, "cwd").mockReturnValueOnce(null); + if (!global) jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); await handler.process(params as IHandlerParameters); expect(ensureCredMgrSpy).toHaveBeenCalledTimes(1); expect(setSchemaSpy).toHaveBeenCalledTimes(1); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(user ? 0 : 1); - expect(editFileSpy).toHaveBeenCalledWith(ImperativeConfig.instance.config.layerActive().path); + expect(readPromptSpy).toHaveBeenCalledTimes(user ? 0 : 1); + expect(editFileSpy).toHaveBeenCalledWith(ImperativeConfig.instance.config.layerActive().path, undefined); expect(writeFileSyncSpy).toHaveBeenCalledTimes(2); - if (!user) expect(ImperativeConfig.instance.config.properties.profiles.base.properties.secret).toEqual("fakeValue"); + if (!user) expect(ImperativeConfig.instance.config.properties.profiles[baseProfName].properties.secret).toEqual("fakeValue"); }); })); @@ -421,6 +436,7 @@ describe("Configuration Initialization command handler", () => { const params = getIHandlerParametersObject(); params.arguments.userConfig = false; params.arguments.globalConfig = false; + const baseProfName = "project_base"; existsSyncSpy.mockReturnValue(false); // No files exist searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath); // Give search something to return @@ -433,23 +449,23 @@ describe("Configuration Initialization command handler", () => { searchSpy.mockClear(); // initWithSchema - const promptWithTimeoutSpy = jest.fn(() => "true"); - (params.response.console as any).prompt = promptWithTimeoutSpy; + const readPromptSpy = jest.fn(() => "true"); + (params.response.console as any).prompt = readPromptSpy; writeFileSyncSpy.mockImplementation(); // Don't actually write files - jest.spyOn(process, "cwd").mockReturnValueOnce(null); + jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); await handler.process(params as IHandlerParameters); const compObj: any = { $schema: "./fakeapp.schema.json" }; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles[baseProfName].properties.secret; // Delete the secret expect(setSchemaSpy).toHaveBeenCalledTimes(1); expect(setSchemaSpy).toHaveBeenCalledWith(expectedSchemaObject); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(1); + expect(readPromptSpy).toHaveBeenCalledTimes(1); // Prompting for secure property - expect(promptWithTimeoutSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); + expect(readPromptSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); expect(writeFileSyncSpy).toHaveBeenCalledTimes(2); // 1 = Schema and 2 = Config @@ -457,7 +473,7 @@ describe("Configuration Initialization command handler", () => { expect(writeFileSyncSpy).toHaveBeenNthCalledWith(2, fakeProjPath, JSON.stringify(compObj, null, ConfigConstants.INDENT)); // Secure value supplied during prompting should be on properties - expect(ImperativeConfig.instance.config.properties.profiles.base.properties.secret).toEqual(true); + expect(ImperativeConfig.instance.config.properties.profiles[baseProfName].properties.secret).toEqual(true); }); it("should attempt to initialize the project configuration and use boolean false for the prompt", async () => { @@ -465,6 +481,7 @@ describe("Configuration Initialization command handler", () => { const params = getIHandlerParametersObject(); params.arguments.userConfig = false; params.arguments.globalConfig = false; + const baseProfName = "project_base"; existsSyncSpy.mockReturnValue(false); // No files exist searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath); // Give search something to return @@ -477,23 +494,23 @@ describe("Configuration Initialization command handler", () => { searchSpy.mockClear(); // initWithSchema - const promptWithTimeoutSpy = jest.fn(() => "false"); - (params.response.console as any).prompt = promptWithTimeoutSpy; + const readPromptSpy = jest.fn(() => "false"); + (params.response.console as any).prompt = readPromptSpy; writeFileSyncSpy.mockImplementation(); // Don't actually write files - jest.spyOn(process, "cwd").mockReturnValueOnce(null); + jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); await handler.process(params as IHandlerParameters); const compObj: any = { $schema: "./fakeapp.schema.json" }; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles[baseProfName].properties.secret; // Delete the secret expect(setSchemaSpy).toHaveBeenCalledTimes(1); expect(setSchemaSpy).toHaveBeenCalledWith(expectedSchemaObject); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(1); + expect(readPromptSpy).toHaveBeenCalledTimes(1); // Prompting for secure property - expect(promptWithTimeoutSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); + expect(readPromptSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); expect(writeFileSyncSpy).toHaveBeenCalledTimes(2); // 1 = Schema and 2 = Config @@ -501,7 +518,7 @@ describe("Configuration Initialization command handler", () => { expect(writeFileSyncSpy).toHaveBeenNthCalledWith(2, fakeProjPath, JSON.stringify(compObj, null, ConfigConstants.INDENT)); // Secure value supplied during prompting should be on properties - expect(ImperativeConfig.instance.config.properties.profiles.base.properties.secret).toEqual(false); + expect(ImperativeConfig.instance.config.properties.profiles[baseProfName].properties.secret).toEqual(false); }); it("should attempt to initialize the project configuration and use a number for the prompt", async () => { @@ -509,6 +526,7 @@ describe("Configuration Initialization command handler", () => { const params = getIHandlerParametersObject(); params.arguments.userConfig = false; params.arguments.globalConfig = false; + const baseProfName = "project_base"; existsSyncSpy.mockReturnValue(false); // No files exist searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath); // Give search something to return @@ -523,23 +541,23 @@ describe("Configuration Initialization command handler", () => { // initWithSchema const randomValueString = "9001"; const randomValueNumber = parseInt(randomValueString, 10); - const promptWithTimeoutSpy = jest.fn(() => randomValueString); - (params.response.console as any).prompt = promptWithTimeoutSpy; + const readPromptSpy = jest.fn(() => randomValueString); + (params.response.console as any).prompt = readPromptSpy; writeFileSyncSpy.mockImplementation(); // Don't actually write files - jest.spyOn(process, "cwd").mockReturnValueOnce(null); + jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); await handler.process(params as IHandlerParameters); const compObj: any = { $schema: "./fakeapp.schema.json" }; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles[baseProfName].properties.secret; // Delete the secret expect(setSchemaSpy).toHaveBeenCalledTimes(1); expect(setSchemaSpy).toHaveBeenCalledWith(expectedSchemaObject); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(1); + expect(readPromptSpy).toHaveBeenCalledTimes(1); // Prompting for secure property - expect(promptWithTimeoutSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); + expect(readPromptSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); expect(writeFileSyncSpy).toHaveBeenCalledTimes(2); // 1 = Schema and 2 = Config @@ -547,7 +565,7 @@ describe("Configuration Initialization command handler", () => { expect(writeFileSyncSpy).toHaveBeenNthCalledWith(2, fakeProjPath, JSON.stringify(compObj, null, ConfigConstants.INDENT)); // Secure value supplied during prompting should be on properties - expect(ImperativeConfig.instance.config.properties.profiles.base.properties.secret).toEqual(randomValueNumber); + expect(ImperativeConfig.instance.config.properties.profiles[baseProfName].properties.secret).toEqual(randomValueNumber); }); it("should attempt to initialize the project configuration and handle getting nothing from the prompt", async () => { @@ -555,6 +573,7 @@ describe("Configuration Initialization command handler", () => { const params = getIHandlerParametersObject(); params.arguments.userConfig = false; params.arguments.globalConfig = false; + const baseProfName = "project_base"; existsSyncSpy.mockReturnValue(false); // No files exist searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath); // Give search something to return @@ -567,23 +586,23 @@ describe("Configuration Initialization command handler", () => { searchSpy.mockClear(); // initWithSchema - const promptWithTimeoutSpy = jest.fn(() => undefined); - (params.response.console as any).prompt = promptWithTimeoutSpy; + const readPromptSpy = jest.fn(() => undefined); + (params.response.console as any).prompt = readPromptSpy; writeFileSyncSpy.mockImplementation(); // Don't actually write files - jest.spyOn(process, "cwd").mockReturnValueOnce(null); + jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); await handler.process(params as IHandlerParameters); const compObj: any = { $schema: "./fakeapp.schema.json" }; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles[baseProfName].properties.secret; // Delete the secret expect(setSchemaSpy).toHaveBeenCalledTimes(1); expect(setSchemaSpy).toHaveBeenCalledWith(expectedSchemaObject); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(1); + expect(readPromptSpy).toHaveBeenCalledTimes(1); // Prompting for secure property - expect(promptWithTimeoutSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); + expect(readPromptSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); expect(writeFileSyncSpy).toHaveBeenCalledTimes(2); // 1 = Schema and 2 = Config @@ -591,7 +610,7 @@ describe("Configuration Initialization command handler", () => { expect(writeFileSyncSpy).toHaveBeenNthCalledWith(2, fakeProjPath, JSON.stringify(compObj, null, ConfigConstants.INDENT)); // Secure value supplied during prompting should be on properties - expect(ImperativeConfig.instance.config.properties.profiles.base.properties.secret).toEqual(undefined); + expect(ImperativeConfig.instance.config.properties.profiles[baseProfName].properties.secret).toEqual(undefined); }); it("should attempt to initialize the project configuration and overwrite empty value with prompt", async () => { @@ -599,12 +618,13 @@ describe("Configuration Initialization command handler", () => { const params = getIHandlerParametersObject(); params.arguments.userConfig = false; params.arguments.globalConfig = false; + const baseProfName = "project_base"; existsSyncSpy.mockReturnValueOnce(false).mockReturnValueOnce(true).mockReturnValue(false); // Project config exists searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath); // Give search something to return jest.spyOn(fs, "readFileSync").mockReturnValueOnce(JSON.stringify({ profiles: { - base: { + project_base: { properties: { secret: "" } @@ -621,23 +641,23 @@ describe("Configuration Initialization command handler", () => { searchSpy.mockClear(); // initWithSchema - const promptWithTimeoutSpy = jest.fn(() => "area51"); - (params.response.console as any).prompt = promptWithTimeoutSpy; + const readPromptSpy = jest.fn(() => "area51"); + (params.response.console as any).prompt = readPromptSpy; writeFileSyncSpy.mockImplementation(); // Don't actually write files - jest.spyOn(process, "cwd").mockReturnValueOnce(null); + jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); await handler.process(params as IHandlerParameters); const compObj: any = { $schema: "./fakeapp.schema.json" }; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles[baseProfName].properties.secret; // Delete the secret expect(setSchemaSpy).toHaveBeenCalledTimes(1); expect(setSchemaSpy).toHaveBeenCalledWith(expectedSchemaObject); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(1); + expect(readPromptSpy).toHaveBeenCalledTimes(1); // Prompting for secure property - expect(promptWithTimeoutSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); + expect(readPromptSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); expect(writeFileSyncSpy).toHaveBeenCalledTimes(2); // 1 = Schema and 2 = Config @@ -645,7 +665,7 @@ describe("Configuration Initialization command handler", () => { expect(writeFileSyncSpy).toHaveBeenNthCalledWith(2, fakeProjPath, JSON.stringify(compObj, null, ConfigConstants.INDENT)); // Secure value supplied during prompting should be on properties - expect(ImperativeConfig.instance.config.properties.profiles.base.properties.secret).toEqual("area51"); + expect(ImperativeConfig.instance.config.properties.profiles[baseProfName].properties.secret).toEqual("area51"); }); it("should attempt to initialize the project configuration and overwrite non-empty value with prompt", async () => { @@ -653,12 +673,13 @@ describe("Configuration Initialization command handler", () => { const params = getIHandlerParametersObject(); params.arguments.userConfig = false; params.arguments.globalConfig = false; + const baseProfName = "project_base"; existsSyncSpy.mockReturnValueOnce(false).mockReturnValueOnce(true).mockReturnValue(false); // Project config exists searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath); // Give search something to return jest.spyOn(fs, "readFileSync").mockReturnValueOnce(JSON.stringify({ profiles: { - base: { + project_base: { properties: { secret: "expired" } @@ -675,23 +696,23 @@ describe("Configuration Initialization command handler", () => { searchSpy.mockClear(); // initWithSchema - const promptWithTimeoutSpy = jest.fn(() => "area51"); - (params.response.console as any).prompt = promptWithTimeoutSpy; + const readPromptSpy = jest.fn(() => "area51"); + (params.response.console as any).prompt = readPromptSpy; writeFileSyncSpy.mockImplementation(); // Don't actually write files - jest.spyOn(process, "cwd").mockReturnValueOnce(null); + jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); await handler.process(params as IHandlerParameters); const compObj: any = { $schema: "./fakeapp.schema.json" }; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles[baseProfName].properties.secret; // Delete the secret expect(setSchemaSpy).toHaveBeenCalledTimes(1); expect(setSchemaSpy).toHaveBeenCalledWith(expectedSchemaObject); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(1); + expect(readPromptSpy).toHaveBeenCalledTimes(1); // Prompting for secure property - expect(promptWithTimeoutSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); + expect(readPromptSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); expect(writeFileSyncSpy).toHaveBeenCalledTimes(2); // 1 = Schema and 2 = Config @@ -699,7 +720,7 @@ describe("Configuration Initialization command handler", () => { expect(writeFileSyncSpy).toHaveBeenNthCalledWith(2, fakeProjPath, JSON.stringify(compObj, null, ConfigConstants.INDENT)); // Secure value supplied during prompting should be on properties - expect(ImperativeConfig.instance.config.properties.profiles.base.properties.secret).toEqual("area51"); + expect(ImperativeConfig.instance.config.properties.profiles[baseProfName].properties.secret).toEqual("area51"); }); it("should attempt to initialize the project configuration and not overwrite value when prompt is skipped", async () => { @@ -707,12 +728,13 @@ describe("Configuration Initialization command handler", () => { const params = getIHandlerParametersObject(); params.arguments.userConfig = false; params.arguments.globalConfig = false; + const baseProfName = "project_base"; existsSyncSpy.mockReturnValueOnce(false).mockReturnValueOnce(true).mockReturnValue(false); // Project config exists searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath); // Give search something to return jest.spyOn(fs, "readFileSync").mockReturnValueOnce(JSON.stringify({ profiles: { - base: { + project_base: { properties: { info: "fakeValue", secret: "area51" @@ -731,23 +753,23 @@ describe("Configuration Initialization command handler", () => { searchSpy.mockClear(); // initWithSchema - const promptWithTimeoutSpy = jest.fn(() => ""); - (params.response.console as any).prompt = promptWithTimeoutSpy; + const readPromptSpy = jest.fn(() => ""); + (params.response.console as any).prompt = readPromptSpy; writeFileSyncSpy.mockImplementation(); // Don't actually write files - jest.spyOn(process, "cwd").mockReturnValueOnce(null); + jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); await handler.process(params as IHandlerParameters); const compObj: any = { $schema: "./fakeapp.schema.json" }; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles[baseProfName].properties.secret; // Delete the secret expect(setSchemaSpy).toHaveBeenCalledTimes(1); expect(setSchemaSpy).toHaveBeenCalledWith(expectedSchemaObject); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(2); + expect(readPromptSpy).toHaveBeenCalledTimes(2); // Prompting for secure property - expect(promptWithTimeoutSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); + expect(readPromptSpy).toHaveBeenCalledWith(expect.stringContaining("to skip:"), {"hideText": true}); expect(writeFileSyncSpy).toHaveBeenCalledTimes(2); // 1 = Schema and 2 = Config @@ -755,8 +777,8 @@ describe("Configuration Initialization command handler", () => { expect(writeFileSyncSpy).toHaveBeenNthCalledWith(2, fakeProjPath, JSON.stringify(compObj, null, ConfigConstants.INDENT)); // Secure value supplied during prompting should be on properties - expect(ImperativeConfig.instance.config.properties.profiles.base.properties.info).toEqual("fakeValue"); - expect(ImperativeConfig.instance.config.properties.profiles.base.properties.secret).toEqual("area51"); + expect(ImperativeConfig.instance.config.properties.profiles[baseProfName].properties.info).toEqual("fakeValue"); + expect(ImperativeConfig.instance.config.properties.profiles[baseProfName].properties.secret).toEqual("area51"); }); it("should display warning if unable to securely save credentials", async () => { @@ -764,6 +786,7 @@ describe("Configuration Initialization command handler", () => { const params = getIHandlerParametersObject(); params.arguments.userConfig = false; params.arguments.globalConfig = false; + const baseProfName = "project_base"; existsSyncSpy.mockReturnValue(false); // No files exist searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath); // Give search something to return @@ -776,22 +799,104 @@ describe("Configuration Initialization command handler", () => { searchSpy.mockClear(); // initWithSchema - const promptWithTimeoutSpy = jest.fn(() => undefined); - (params.response.console as any).prompt = promptWithTimeoutSpy; + const readPromptSpy = jest.fn(() => undefined); + (params.response.console as any).prompt = readPromptSpy; writeFileSyncSpy.mockImplementation(); // Don't actually write files jest.spyOn(CredentialManagerFactory, "initialized", "get").mockReturnValue(false); jest.spyOn(CredentialManagerFactory, "manager", "get").mockReturnValue({ secureErrorDetails: jest.fn() } as any); - jest.spyOn(process, "cwd").mockReturnValueOnce(null); + jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); await handler.process(params as IHandlerParameters); const compObj: any = { $schema: "./fakeapp.schema.json" }; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles[baseProfName].properties.secret; // Delete the secret - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(0); + expect(readPromptSpy).toHaveBeenCalledTimes(0); expect(writeFileSyncSpy).toHaveBeenCalledTimes(2); expect(params.response.console.log).toHaveBeenCalledTimes(2); expect((params.response.console.log as any).mock.calls[0][0]).toContain("Unable to securely save credentials"); }); + + it("should display correct error message for process() given additionalDetails property is defined in ImperativeError", async () => { + const handler = new InitHandler(); + const params = getIHandlerParametersObject(); + params.arguments.userConfig = false; + params.arguments.globalConfig = false; + + existsSyncSpy.mockReturnValue(false); // No files exist + searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath); // Give search something to return + await setupConfigToLoad(); // Setup the config + + setSchemaSpy = jest.spyOn(ImperativeConfig.instance.config, "setSchema"); + + // We aren't testing the config initialization - clear the spies + existsSyncSpy.mockClear(); + searchSpy.mockClear(); + + // initWithSchema + const readPromptSpy = jest.fn(() => undefined); + (params.response.console as any).prompt = readPromptSpy; + writeFileSyncSpy.mockImplementation(); // Don't actually write files + jest.spyOn(CredentialManagerFactory, "initialized", "get").mockReturnValue(false); + jest.spyOn(CredentialManagerFactory, "manager", "get").mockReturnValue({ secureErrorDetails: jest.fn() } as any); + + jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); + + // Mocking for logical branch intended to evaluate + const secureSaveErrorSpy = jest.spyOn(ConfigUtils, "secureSaveError"); + + secureSaveErrorSpy.mockImplementation(() => { + return new ImperativeError({ + msg: "fake message", + additionalDetails: "fake additional details" + }); + }); + + await handler.process(params as IHandlerParameters); + + expect(secureSaveErrorSpy.mock.results[0].value).toBeInstanceOf(ImperativeError); + expect(secureSaveErrorSpy.mock.results[0].value.additionalDetails).toEqual( + "fake additional details"); + expect((params.response.console.log as any).mock.calls[0][0]).toContain("fake additional details"); + }); + it("should display correct error message for process() given additionalDetails property is NOT defined in ImperativeError", async () => { + const handler = new InitHandler(); + const params = getIHandlerParametersObject(); + params.arguments.userConfig = false; + params.arguments.globalConfig = false; + + existsSyncSpy.mockReturnValue(false); // No files exist + searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath); // Give search something to return + await setupConfigToLoad(); // Setup the config + + setSchemaSpy = jest.spyOn(ImperativeConfig.instance.config, "setSchema"); + + // We aren't testing the config initialization - clear the spies + existsSyncSpy.mockClear(); + searchSpy.mockClear(); + + // initWithSchema + const readPromptSpy = jest.fn(() => undefined); + (params.response.console as any).prompt = readPromptSpy; + writeFileSyncSpy.mockImplementation(); // Don't actually write files + jest.spyOn(CredentialManagerFactory, "initialized", "get").mockReturnValue(false); + jest.spyOn(CredentialManagerFactory, "manager", "get").mockReturnValue({ secureErrorDetails: jest.fn() } as any); + + jest.spyOn(process, "cwd").mockReturnValueOnce(null as unknown as string); + + // Mocking for logical branch intended to evaluate + const secureSaveErrorSpy = jest.spyOn(ConfigUtils, "secureSaveError"); + + secureSaveErrorSpy.mockImplementation(() => { + return new ImperativeError({ + msg: "fake message" + }); + }); + + await handler.process(params as IHandlerParameters); + + expect(secureSaveErrorSpy.mock.results[0].value).toBeInstanceOf(ImperativeError); + expect((params.response.console.log as any).mock.calls[0][0]).not.toContain("fake additional details"); + }); }); diff --git a/packages/imperative/src/imperative/__tests__/config/cmd/list/list.handler.unit.test.ts b/packages/imperative/src/imperative/__tests__/config/cmd/list/list.handler.unit.test.ts index 9651183eb9..6423288d72 100644 --- a/packages/imperative/src/imperative/__tests__/config/cmd/list/list.handler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/config/cmd/list/list.handler.unit.test.ts @@ -100,7 +100,7 @@ describe("Configuration List command handler", () => { jest.spyOn(fakeConfig, "exists", "get").mockReturnValueOnce(false); handlerParms.arguments = {}; - await (new ListHandler()).process(handlerParms); + await new ListHandler().process(handlerParms); expect(errorText).toBeNull(); expect(dataObj).toEqual({}); expect(formatObj).toEqual(dataObj); @@ -110,7 +110,7 @@ describe("Configuration List command handler", () => { (fakeConfig as any).mLayers = configLayers; handlerParms.arguments = {}; - await (new ListHandler()).process(handlerParms); + await new ListHandler().process(handlerParms); expect(errorText).toBeNull(); expect(dataObj).toEqual(configMaskedProps); expect(dataObj.profiles.email.properties.user).toBe(ConfigConstants.SECURE_VALUE); @@ -122,7 +122,7 @@ describe("Configuration List command handler", () => { (fakeConfig as any).mLayers = configLayers; handlerParms.arguments = { property: "plugins" }; - await (new ListHandler()).process(handlerParms); + await new ListHandler().process(handlerParms); expect(errorText).toBeNull(); expect(dataObj).toEqual(["fakePlugin"]); expect(formatObj).toEqual(dataObj); @@ -132,7 +132,7 @@ describe("Configuration List command handler", () => { (fakeConfig as any).mLayers = configLayers; handlerParms.arguments = { locations: true }; - await (new ListHandler()).process(handlerParms); + await new ListHandler().process(handlerParms); expect(errorText).toBeNull(); expect(dataObj.fakePath).toEqual(configMaskedProps); expect(dataObj.fakePath.profiles.email.properties.user).toBe(ConfigConstants.SECURE_VALUE); @@ -144,7 +144,7 @@ describe("Configuration List command handler", () => { (fakeConfig as any).mLayers = configLayers; handlerParms.arguments = { locations: true, property: "plugins" }; - await (new ListHandler()).process(handlerParms); + await new ListHandler().process(handlerParms); expect(errorText).toBeNull(); expect(dataObj.fakePath).toEqual(["fakePlugin"]); expect(formatObj).toEqual(dataObj); @@ -154,7 +154,7 @@ describe("Configuration List command handler", () => { (fakeConfig as any).mLayers = configLayers; handlerParms.arguments = { locations: true, property: "profiles" }; - await (new ListHandler()).process(handlerParms); + await new ListHandler().process(handlerParms); expect(errorText).toBeNull(); expect(dataObj.fakePath).toEqual(configMaskedProps.profiles); expect(dataObj.fakePath.email.properties.user).toBe(ConfigConstants.SECURE_VALUE); @@ -164,9 +164,9 @@ describe("Configuration List command handler", () => { it("should output entire config at root level", async () => { (fakeConfig as any).mLayers = configLayers; - handlerParms.arguments = { root: true }; + handlerParms.arguments = { nameOnly: true }; - await (new ListHandler()).process(handlerParms); + await new ListHandler().process(handlerParms); expect(errorText).toBeNull(); expect(dataObj).toEqual(Object.keys(configLayers[0].properties)); expect(formatObj).toEqual(dataObj); diff --git a/packages/imperative/src/imperative/__tests__/config/cmd/profiles/profiles.handler.unit.test.ts b/packages/imperative/src/imperative/__tests__/config/cmd/profiles/profiles.handler.unit.test.ts index cdd0b68689..de832b3f68 100644 --- a/packages/imperative/src/imperative/__tests__/config/cmd/profiles/profiles.handler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/config/cmd/profiles/profiles.handler.unit.test.ts @@ -93,7 +93,7 @@ describe("Configuration Profiles command handler", () => { properties: configProps }); - await (new ProfilesHandler()).process(handlerParms); + await new ProfilesHandler().process(handlerParms); expect(errorText).toBeNull(); expect(dataObj).toEqual(["email", "email.incoming", "email.outgoing"]); expect(formatObj).toEqual(dataObj); diff --git a/packages/imperative/src/imperative/__tests__/config/cmd/report-env/EnvQuery.unit.test.ts b/packages/imperative/src/imperative/__tests__/config/cmd/report-env/EnvQuery.unit.test.ts index 7a426f180c..568d8156db 100644 --- a/packages/imperative/src/imperative/__tests__/config/cmd/report-env/EnvQuery.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/config/cmd/report-env/EnvQuery.unit.test.ts @@ -9,12 +9,10 @@ * */ -import * as fs from "fs"; import * as os from "os"; import * as path from "path"; import { CommandResponse } from "../../../../../cmd/src/response/CommandResponse"; -import { IO } from "../../../../../io"; import { ImperativeConfig } from "../../../../../utilities"; import { PluginIssues } from "../../../../src/plugins/utilities/PluginIssues"; @@ -54,7 +52,7 @@ describe("Tests for EnvQuery module", () => { } }); - // set ImperativeConfig properties for a v2 config + // set ImperativeConfig properties for a team config impCfg = ImperativeConfig.instance; impCfg.rootCommandName = "zowe"; (impCfg.loadedConfig as any) = { daemonMode: false }; @@ -136,15 +134,6 @@ describe("Tests for EnvQuery module", () => { expect(itemObj.itemProbMsg).toBe(""); }); - it("should report the NVM version", async () => { - const itemObj: IGetItemVal = await EnvQuery.getEnvItemVal(ItemId.NVM_VER); - if (!itemObj.itemVal.includes("nvm failed to display any output")) { - expect(itemObj.itemVal).toMatch(/[0-9]+.[0-9]+.[0-9]+/); - expect(itemObj.itemValMsg).toContain("Node Version Manager version ="); - } - expect(itemObj.itemProbMsg).toBe(""); - }); - it("should report the platform", async () => { const itemObj: IGetItemVal = await EnvQuery.getEnvItemVal(ItemId.PLATFORM); expect(itemObj.itemVal === "win32" || itemObj.itemVal === "linux" || itemObj.itemVal === "darwin").toBeTruthy(); @@ -283,16 +272,14 @@ describe("Tests for EnvQuery module", () => { }); it("should report an unknown item id", async () => { - const itemObj: IGetItemVal = await EnvQuery.getEnvItemVal(999); + const itemObj: IGetItemVal = await EnvQuery.getEnvItemVal(999 as ItemId); expect(itemObj.itemProbMsg).toBe("An unknown item ID was supplied = 999"); }); - it("should report Zowe V2 configuration info", async () => { - const itemObj: IGetItemVal = await EnvQuery.getEnvItemVal(ItemId.ZOWE_CONFIG_TYPE); - expect(itemObj.itemVal).toContain("V2 Team Config"); + it("should report Zowe team configuration info", async () => { + const itemObj: IGetItemVal = await EnvQuery.getEnvItemVal(ItemId.ZOWE_CONFIG_INFO); expect(itemObj.itemValMsg).toContain("Zowe daemon mode = off"); - expect(itemObj.itemValMsg).toContain("Zowe config type = V2 Team Config"); - expect(itemObj.itemValMsg).toContain("Team config files in effect:"); + expect(itemObj.itemValMsg).toContain("Zowe client config files in use:"); expect(itemObj.itemValMsg).toContain("fakeDir/zowe.config.json"); expect(itemObj.itemValMsg).toMatch(/base = +fakeBaseProfNm/); expect(itemObj.itemValMsg).toMatch(/zosmf = +fakeZosmfProfNm/); @@ -306,70 +293,12 @@ describe("Tests for EnvQuery module", () => { (impCfg.loadedConfig as any) = { daemonMode: true }; // return the values that we want from external commands - const itemObj: IGetItemVal = await EnvQuery.getEnvItemVal(ItemId.ZOWE_CONFIG_TYPE); - expect(itemObj.itemVal).toContain("V2 Team Config"); + const itemObj: IGetItemVal = await EnvQuery.getEnvItemVal(ItemId.ZOWE_CONFIG_INFO); expect(itemObj.itemValMsg).toContain("Zowe daemon mode = on"); expect(itemObj.itemValMsg).toMatch(/Default Zowe daemon executable directory = this_is_a_fake_cli_home_dir.bin/); expect(itemObj.itemProbMsg).toBe(""); }); - it("should report Zowe V1 configuration info", async () => { - // set ImperativeConfig properties to what we want - Object.defineProperty(impCfg, "config", { - configurable: true, - get: jest.fn(() => { - return { - exists: false - }; - }) - }); - - const isDirSpy = jest.spyOn(IO as any, "isDir") - .mockReturnValue(true); - - const endvProfDir = "endevor"; - const tsoProfDir = "tso"; - const zosmfProfDir = "zosmf"; - const prof1 = "_prof_1"; - const prof2 = "_prof_2"; - const prof3 = "_prof_3"; - const readDirSyncSpy = jest.spyOn(fs, "readdirSync") - .mockReturnValueOnce([ - endvProfDir as unknown as fs.Dirent, - tsoProfDir as unknown as fs.Dirent, - zosmfProfDir as unknown as fs.Dirent - ]).mockReturnValueOnce([ - endvProfDir + prof1 as unknown as fs.Dirent, - endvProfDir + prof2 as unknown as fs.Dirent, - endvProfDir + prof3 as unknown as fs.Dirent - ]).mockReturnValueOnce([ - tsoProfDir + prof1 as unknown as fs.Dirent, - tsoProfDir + prof2 as unknown as fs.Dirent, - tsoProfDir + prof3 as unknown as fs.Dirent - ]).mockReturnValueOnce([ - zosmfProfDir + prof1 as unknown as fs.Dirent, - zosmfProfDir + prof2 as unknown as fs.Dirent, - zosmfProfDir + prof3 as unknown as fs.Dirent - ]); - - const itemObj: IGetItemVal = await EnvQuery.getEnvItemVal(ItemId.ZOWE_CONFIG_TYPE); - expect(itemObj.itemVal).toContain("V1 Profiles"); - expect(itemObj.itemValMsg).toContain("Zowe config type = V1 Profiles"); - expect(itemObj.itemValMsg).toContain("Available profiles:"); - expect(itemObj.itemValMsg).toContain(endvProfDir + " profiles:"); - expect(itemObj.itemValMsg).toContain(endvProfDir + prof1); - expect(itemObj.itemValMsg).toContain(endvProfDir + prof2); - expect(itemObj.itemValMsg).toContain(endvProfDir + prof3); - expect(itemObj.itemValMsg).toContain(tsoProfDir + " profiles:"); - expect(itemObj.itemValMsg).toContain(tsoProfDir + prof1); - expect(itemObj.itemValMsg).toContain(tsoProfDir + prof2); - expect(itemObj.itemValMsg).toContain(tsoProfDir + prof3); - expect(itemObj.itemValMsg).toContain(zosmfProfDir + " profiles:"); - expect(itemObj.itemValMsg).toContain(zosmfProfDir + prof1); - expect(itemObj.itemValMsg).toContain(zosmfProfDir + prof2); - expect(itemObj.itemValMsg).toContain(zosmfProfDir + prof3); - expect(itemObj.itemProbMsg).toBe(""); - }); }); // end getEnvItemVal function describe("test getCmdOutput", () => { diff --git a/packages/imperative/src/imperative/__tests__/config/cmd/schema/schema.handler.unit.test.ts b/packages/imperative/src/imperative/__tests__/config/cmd/schema/schema.handler.unit.test.ts index fc726fa006..3abd5d11a6 100644 --- a/packages/imperative/src/imperative/__tests__/config/cmd/schema/schema.handler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/config/cmd/schema/schema.handler.unit.test.ts @@ -103,7 +103,7 @@ describe("Configuration Schema command handler", () => { profiles: testProfileConfiguration }); - await (new SchemaHandler()).process(handlerParms); + await new SchemaHandler().process(handlerParms); expect(errorText).toBeNull(); expect(dataObj).toMatchObject(expectedSchemaObj); expect(JSON.parse(logText)).toMatchObject(dataObj); @@ -112,7 +112,7 @@ describe("Configuration Schema command handler", () => { it("should fail when Imperative config not loaded", async () => { loadedConfigMock.mockReturnValueOnce(undefined); - await (new SchemaHandler()).process(handlerParms); + await new SchemaHandler().process(handlerParms); expect(errorText).toBe("Failed to load profile schemas"); expect(logText).toBeNull(); }); diff --git a/packages/imperative/src/imperative/__tests__/config/cmd/secure/secure.handler.unit.test.ts b/packages/imperative/src/imperative/__tests__/config/cmd/secure/secure.handler.unit.test.ts index d3adb82832..c3194cc9c6 100644 --- a/packages/imperative/src/imperative/__tests__/config/cmd/secure/secure.handler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/config/cmd/secure/secure.handler.unit.test.ts @@ -9,14 +9,14 @@ * */ -import { IHandlerParameters, Logger } from "../../../../.."; +import { Logger } from "../../../../../logger"; import { Config } from "../../../../../config/src/Config"; import { IConfig, IConfigOpts, IConfigProfile } from "../../../../../config"; import { ImperativeConfig } from "../../../../../utilities"; import { IImperativeConfig } from "../../../../src/doc/IImperativeConfig"; import { ICredentialManagerInit } from "../../../../../security/src/doc/ICredentialManagerInit"; import { CredentialManagerFactory } from "../../../../../security"; -import { expectedConfigObject } from +import { expectedGlobalConfigObject, expectedGlobalUserConfigObject, expectedProjectConfigObject, expectedProjectUserConfigObject } from "../../../../../../__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/expectedObjects"; import SecureHandler from "../../../../src/config/cmd/secure/secure.handler"; import * as config from "../../../../../../__tests__/__integration__/imperative/src/imperative"; @@ -26,7 +26,10 @@ import * as lodash from "lodash"; import * as fs from "fs"; import { SessConstants } from "../../../../../rest"; import { setupConfigToLoad } from "../../../../../../__tests__/src/TestUtil"; +import { IHandlerParameters } from "../../../../../cmd"; +import { EventOperator, EventUtils } from "../../../../../events"; +let readPromptSpy: any; const getIHandlerParametersObject = (): IHandlerParameters => { const x: any = { response: { @@ -45,7 +48,8 @@ const getIHandlerParametersObject = (): IHandlerParameters => { error: jest.fn((errors) => { // Nothing }), - errorHeader: jest.fn(() => undefined) + errorHeader: jest.fn(() => undefined), + prompt: readPromptSpy } }, arguments: {}, @@ -70,9 +74,9 @@ const fakeGblProjUserPath = path.join(__dirname, ".fakeapp", "fakeapp.config.use const fakeUnrelatedPath = path.join(__dirname, "fakeapp.unrelated.config.json"); const fakeSecureDataJson: any = {}; -fakeSecureDataJson[fakeProjPath] = {"profiles.base.properties.secure": "fakeSecureValue"}; -fakeSecureDataJson[fakeGblProjPath] = {"profiles.base.properties.secure": "fakeSecureValue"}; -fakeSecureDataJson[fakeUnrelatedPath] = {"profiles.base.properties.secure": "anotherFakeSecureValue"}; +fakeSecureDataJson[fakeProjPath] = {"profiles.project_base.properties.secure": "fakeSecureValue"}; +fakeSecureDataJson[fakeGblProjPath] = {"profiles.global_base.properties.secure": "fakeSecureValue"}; +fakeSecureDataJson[fakeUnrelatedPath] = {"profiles.project_base.properties.secure": "anotherFakeSecureValue"}; const fakeSecureData = Buffer.from(JSON.stringify(fakeSecureDataJson)).toString("base64"); @@ -86,14 +90,15 @@ describe("Configuration Secure command handler", () => { let keytarSetPasswordSpy: any; let keytarDeletePasswordSpy: any; + readPromptSpy = jest.fn().mockReturnValue("fakePromptingData"); const configOpts: IConfigOpts = { vault: { - load: ((k: string): Promise => { + load: (k: string): Promise => { return CredentialManagerFactory.manager.load(k, true); - }), - save: ((k: string, v: any): Promise => { + }, + save: (k: string, v: any): Promise => { return CredentialManagerFactory.manager.save(k, v); - }) + } } }; @@ -118,6 +123,10 @@ describe("Configuration Secure command handler", () => { keytarGetPasswordSpy = jest.spyOn(keytar, "getPassword"); keytarSetPasswordSpy = jest.spyOn(keytar, "setPassword"); keytarDeletePasswordSpy = jest.spyOn(keytar, "deletePassword"); + readPromptSpy.mockClear(); + + jest.spyOn(EventUtils, "validateAppName").mockImplementation(jest.fn()); + jest.spyOn(EventOperator, "getZoweProcessor").mockReturnValue({emitZoweEvent: jest.fn()} as any); }); afterEach( () => { @@ -140,7 +149,7 @@ describe("Configuration Secure command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedConfigObject); + const eco = lodash.cloneDeep(expectedProjectConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); @@ -156,16 +165,15 @@ describe("Configuration Secure command handler", () => { existsSyncSpy.mockClear(); readFileSyncSpy.mockClear(); - const promptWithTimeoutSpy: any = jest.fn(() => "fakePromptingData"); - (params.response.console as any).prompt = promptWithTimeoutSpy; setSchemaSpy = jest.spyOn(ImperativeConfig.instance.config, "setSchema"); + (params.response.console as any).prompt = jest.fn(() => "fakePromptingData"); await handler.process(params); const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); delete fakeSecureDataExpectedJson[fakeProjPath]; fakeSecureDataExpectedJson[fakeProjPath] = { - "profiles.base.properties.secret": "fakePromptingData" + "profiles.project_base.properties.secret": "fakePromptingData" }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -173,7 +181,7 @@ describe("Configuration Secure command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles.project_base.properties.secret; // Delete the secret if (process.platform === "win32") { expect(keytarDeletePasswordSpy).toHaveBeenCalledTimes(4); @@ -182,13 +190,12 @@ describe("Configuration Secure command handler", () => { } expect(keytarGetPasswordSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(1); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledWith("Zowe", "secure_config_props", fakeSecureDataExpected); expect(writeFileSyncSpy).toHaveBeenCalledTimes(1); expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeProjPath, JSON.stringify(compObj, null, 4)); // Config }); - it("should attempt to secure the user configuration", async () => { + it("should attempt to secure the project user configuration", async () => { const handler = new SecureHandler(); const params = getIHandlerParametersObject(); @@ -204,7 +211,7 @@ describe("Configuration Secure command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedConfigObject); + const eco = lodash.cloneDeep(expectedProjectUserConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); @@ -220,15 +227,13 @@ describe("Configuration Secure command handler", () => { existsSyncSpy.mockClear(); readFileSyncSpy.mockClear(); - const promptWithTimeoutSpy = jest.fn(() => "fakePromptingData"); - (params.response.console as any).prompt = promptWithTimeoutSpy; setSchemaSpy = jest.spyOn(ImperativeConfig.instance.config, "setSchema"); await handler.process(params); const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); fakeSecureDataExpectedJson[fakeProjUserPath] = { - "profiles.base.properties.secret": "fakePromptingData" + "profiles.project_base.properties.secret": "fakePromptingData" }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -236,7 +241,7 @@ describe("Configuration Secure command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles.project_base.properties.secret; // Delete the secret if (process.platform === "win32") { expect(keytarDeletePasswordSpy).toHaveBeenCalledTimes(4); @@ -245,13 +250,12 @@ describe("Configuration Secure command handler", () => { } expect(keytarGetPasswordSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(1); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledWith("Zowe", "secure_config_props", fakeSecureDataExpected); expect(writeFileSyncSpy).toHaveBeenCalledTimes(1); expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeProjUserPath, JSON.stringify(compObj, null, 4)); // Config }); - it("should attempt to secure the global project configuration", async () => { + it("should attempt to secure the global configuration", async () => { const handler = new SecureHandler(); const params = getIHandlerParametersObject(); @@ -267,14 +271,14 @@ describe("Configuration Secure command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedConfigObject); + const eco = lodash.cloneDeep(expectedGlobalConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); existsSyncSpy.mockReturnValueOnce(false).mockReturnValueOnce(false).mockReturnValueOnce(false) - .mockReturnValueOnce(true).mockReturnValue(false); // Only the global project config exists + .mockReturnValueOnce(true).mockReturnValue(false); // Only the global config exists writeFileSyncSpy.mockImplementation(); - searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath); // Give search something to return + searchSpy.mockReturnValueOnce(fakeGblProjUserPath).mockReturnValueOnce(fakeGblProjPath); // Give search something to return await setupConfigToLoad(undefined, configOpts); // Setup the config @@ -284,8 +288,6 @@ describe("Configuration Secure command handler", () => { existsSyncSpy.mockClear(); readFileSyncSpy.mockClear(); - const promptWithTimeoutSpy = jest.fn(() => "fakePromptingData"); - (params.response.console as any).prompt = promptWithTimeoutSpy; setSchemaSpy = jest.spyOn(ImperativeConfig.instance.config, "setSchema"); await handler.process(params); @@ -293,7 +295,7 @@ describe("Configuration Secure command handler", () => { const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); delete fakeSecureDataExpectedJson[fakeGblProjPath]; fakeSecureDataExpectedJson[fakeGblProjPath] = { - "profiles.base.properties.secret": "fakePromptingData" + "profiles.global_base.properties.secret": "fakePromptingData" }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -301,7 +303,7 @@ describe("Configuration Secure command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles.global_base.properties.secret; // Delete the secret if (process.platform === "win32") { expect(keytarDeletePasswordSpy).toHaveBeenCalledTimes(4); @@ -310,7 +312,6 @@ describe("Configuration Secure command handler", () => { } expect(keytarGetPasswordSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(1); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledWith("Zowe", "secure_config_props", fakeSecureDataExpected); expect(writeFileSyncSpy).toHaveBeenCalledTimes(1); expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeGblProjPath, JSON.stringify(compObj, null, 4)); // Config @@ -332,7 +333,7 @@ describe("Configuration Secure command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedConfigObject); + const eco = lodash.cloneDeep(expectedGlobalUserConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); @@ -349,9 +350,6 @@ describe("Configuration Secure command handler", () => { existsSyncSpy.mockClear(); readFileSyncSpy.mockClear(); - const promptWithTimeoutSpy: any = jest.fn(() => "fakePromptingData"); - (params.response.console as any).prompt = promptWithTimeoutSpy; - setSchemaSpy = jest.spyOn(ImperativeConfig.instance.config, "setSchema"); await handler.process(params); @@ -359,7 +357,7 @@ describe("Configuration Secure command handler", () => { const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); delete fakeSecureDataExpectedJson[fakeGblProjUserPath]; fakeSecureDataExpectedJson[fakeGblProjUserPath] = { - "profiles.base.properties.secret": "fakePromptingData" + "profiles.global_base.properties.secret": "fakePromptingData" }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -367,7 +365,7 @@ describe("Configuration Secure command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles.global_base.properties.secret; // Delete the secret if (process.platform === "win32") { expect(keytarDeletePasswordSpy).toHaveBeenCalledTimes(4); @@ -376,7 +374,6 @@ describe("Configuration Secure command handler", () => { } expect(keytarGetPasswordSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(1); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledWith("Zowe", "secure_config_props", fakeSecureDataExpected); expect(writeFileSyncSpy).toHaveBeenCalledTimes(1); expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeGblProjUserPath, JSON.stringify(compObj, null, 4)); // Config @@ -398,7 +395,7 @@ describe("Configuration Secure command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedConfigObject); + const eco = lodash.cloneDeep(expectedProjectConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); @@ -415,8 +412,6 @@ describe("Configuration Secure command handler", () => { existsSyncSpy.mockClear(); readFileSyncSpy.mockClear(); - const promptWithTimeoutSpy = jest.fn(() => "fakePromptingData"); - (params.response.console as any).prompt = promptWithTimeoutSpy; setSchemaSpy = jest.spyOn(ImperativeConfig.instance.config, "setSchema"); await handler.process(params); @@ -424,7 +419,6 @@ describe("Configuration Secure command handler", () => { expect(keytarDeletePasswordSpy).toHaveBeenCalledTimes(0); expect(keytarGetPasswordSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(0); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(0); expect(writeFileSyncSpy).toHaveBeenCalledTimes(0); expect(ImperativeConfig.instance.config.api.secure.secureFields().length).toEqual(0); }); @@ -446,7 +440,7 @@ describe("Configuration Secure command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedConfigObject); + const eco = lodash.cloneDeep(expectedProjectConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); @@ -462,15 +456,13 @@ describe("Configuration Secure command handler", () => { existsSyncSpy.mockClear(); readFileSyncSpy.mockClear(); - const promptWithTimeoutSpy = jest.fn(() => "fakePromptingData"); - (params.response.console as any).prompt = promptWithTimeoutSpy; setSchemaSpy = jest.spyOn(ImperativeConfig.instance.config, "setSchema"); await handler.process(params); const fakeSecureDataExpectedJson: { [key: string]: any} = { [fakeProjPath]: { - "profiles.base.properties.secret": "fakePromptingData" + "profiles.project_base.properties.secret": "fakePromptingData" } }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -479,7 +471,7 @@ describe("Configuration Secure command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles.project_base.properties.secret; // Delete the secret if (process.platform === "win32") { expect(keytarDeletePasswordSpy).toHaveBeenCalledTimes(8); @@ -488,7 +480,6 @@ describe("Configuration Secure command handler", () => { } expect(keytarGetPasswordSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(2); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledWith("Zowe", "secure_config_props", fakeSecureDataExpected); expect(writeFileSyncSpy).toHaveBeenCalledTimes(1); expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeProjPath, JSON.stringify(compObj, null, 4)); // Config @@ -507,13 +498,13 @@ describe("Configuration Secure command handler", () => { ] }; - const expectedConfigObjectWithToken: IConfig = { + const expectedProjConfigObjectWithToken: IConfig = { $schema: "./fakeapp.schema.json", profiles: { - base: baseProfile, + project_base: baseProfile, }, defaults: { - base: "base" + base: "project_base" } }; @@ -521,7 +512,6 @@ describe("Configuration Secure command handler", () => { const handler = new SecureHandler(); const params = getIHandlerParametersObject(); let mockAuthHandlerApi: any; - let promptWithTimeoutSpy: any; beforeAll(() => { mockAuthHandlerApi = { @@ -558,8 +548,6 @@ describe("Configuration Secure command handler", () => { mockAuthHandlerApi.sessionLogin.mockClear(); writeFileSyncSpy.mockReset(); - promptWithTimeoutSpy = jest.fn(() => "fakePromptingData"); - (params.response.console as any).prompt = promptWithTimeoutSpy; }); afterAll(() => { @@ -567,7 +555,7 @@ describe("Configuration Secure command handler", () => { }); it("should invoke auth handler to obtain token and store it securely", async () => { - const eco = lodash.cloneDeep(expectedConfigObjectWithToken); + const eco = lodash.cloneDeep(expectedProjConfigObjectWithToken); // Create another base profile and mock the loggers to test multiple login operations in a single config-secure eco.profiles["base2"] = baseProfile; @@ -595,7 +583,7 @@ describe("Configuration Secure command handler", () => { const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); delete fakeSecureDataExpectedJson[fakeProjPath]; fakeSecureDataExpectedJson[fakeProjPath] = { - "profiles.base.properties.tokenValue": "fakeLoginData", + "profiles.project_base.properties.tokenValue": "fakeLoginData", "profiles.base2.properties.tokenValue": "fakeLoginData" }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -604,13 +592,12 @@ describe("Configuration Secure command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.tokenValue; // Delete the secret + delete compObj.profiles.project_base.properties.tokenValue; // Delete the secret delete compObj.profiles.base2.properties.tokenValue; // Delete the secret expect(keytarDeletePasswordSpy).toHaveBeenCalledTimes(process.platform === "win32" ? 4 : 3); expect(keytarGetPasswordSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(1); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(4); // User and password expect(mockAuthHandlerApi.createSessCfg).toHaveBeenCalledTimes(2); expect(mockAuthHandlerApi.sessionLogin).toHaveBeenCalledTimes(2); expect(keytarSetPasswordSpy).toHaveBeenCalledWith("Zowe", "secure_config_props", fakeSecureDataExpected); @@ -619,8 +606,8 @@ describe("Configuration Secure command handler", () => { }); it("should not invoke auth handler if profile type is undefined", async () => { - const eco = lodash.cloneDeep(expectedConfigObjectWithToken); - delete eco.profiles.base.type; + const eco = lodash.cloneDeep(expectedProjConfigObjectWithToken); + delete eco.profiles.project_base.type; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); existsSyncSpy.mockReturnValueOnce(false).mockReturnValueOnce(true).mockReturnValue(false); // Only the project config exists @@ -633,7 +620,7 @@ describe("Configuration Secure command handler", () => { const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); delete fakeSecureDataExpectedJson[fakeProjPath]; fakeSecureDataExpectedJson[fakeProjPath] = { - "profiles.base.properties.tokenValue": "fakePromptingData" + "profiles.project_base.properties.tokenValue": "fakePromptingData" }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -641,12 +628,11 @@ describe("Configuration Secure command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.tokenValue; // Delete the secret + delete compObj.profiles.project_base.properties.tokenValue; // Delete the secret expect(keytarDeletePasswordSpy).toHaveBeenCalledTimes(process.platform === "win32" ? 4 : 3); expect(keytarGetPasswordSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(1); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(1); expect(mockAuthHandlerApi.sessionLogin).toHaveBeenCalledTimes(0); expect(keytarSetPasswordSpy).toHaveBeenCalledWith("Zowe", "secure_config_props", fakeSecureDataExpected); expect(writeFileSyncSpy).toHaveBeenCalledTimes(1); @@ -654,8 +640,8 @@ describe("Configuration Secure command handler", () => { }); it("should not invoke auth handler if profile token type is undefined", async () => { - const eco = lodash.cloneDeep(expectedConfigObjectWithToken); - delete eco.profiles.base.properties.tokenType; + const eco = lodash.cloneDeep(expectedProjConfigObjectWithToken); + delete eco.profiles.project_base.properties.tokenType; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); existsSyncSpy.mockReturnValueOnce(false).mockReturnValueOnce(true).mockReturnValue(false); // Only the project config exists @@ -668,7 +654,7 @@ describe("Configuration Secure command handler", () => { const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); delete fakeSecureDataExpectedJson[fakeProjPath]; fakeSecureDataExpectedJson[fakeProjPath] = { - "profiles.base.properties.tokenValue": "fakePromptingData" + "profiles.project_base.properties.tokenValue": "fakePromptingData" }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -676,12 +662,12 @@ describe("Configuration Secure command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.tokenValue; // Delete the secret + delete compObj.profiles.project_base.properties.tokenValue; // Delete the secret expect(keytarDeletePasswordSpy).toHaveBeenCalledTimes(process.platform === "win32" ? 4 : 3); expect(keytarGetPasswordSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(1); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(1); + expect(readPromptSpy).toHaveBeenCalledTimes(1); expect(mockAuthHandlerApi.sessionLogin).toHaveBeenCalledTimes(0); expect(keytarSetPasswordSpy).toHaveBeenCalledWith("Zowe", "secure_config_props", fakeSecureDataExpected); expect(writeFileSyncSpy).toHaveBeenCalledTimes(1); @@ -689,7 +675,7 @@ describe("Configuration Secure command handler", () => { }); it("should not invoke auth handler if no matching auth config is found", async () => { - const eco = lodash.cloneDeep(expectedConfigObjectWithToken); + const eco = lodash.cloneDeep(expectedProjConfigObjectWithToken); readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); existsSyncSpy.mockReturnValueOnce(false).mockReturnValueOnce(true).mockReturnValue(false); // Only the project config exists @@ -710,7 +696,7 @@ describe("Configuration Secure command handler", () => { const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); delete fakeSecureDataExpectedJson[fakeProjPath]; fakeSecureDataExpectedJson[fakeProjPath] = { - "profiles.base.properties.tokenValue": "fakePromptingData" + "profiles.project_base.properties.tokenValue": "fakePromptingData" }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -718,12 +704,12 @@ describe("Configuration Secure command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.tokenValue; // Delete the secret + delete compObj.profiles.project_base.properties.tokenValue; // Delete the secret expect(keytarDeletePasswordSpy).toHaveBeenCalledTimes(process.platform === "win32" ? 4 : 3); expect(keytarGetPasswordSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(1); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(1); + expect(readPromptSpy).toHaveBeenCalledTimes(1); expect(mockAuthHandlerApi.sessionLogin).toHaveBeenCalledTimes(0); expect(keytarSetPasswordSpy).toHaveBeenCalledWith("Zowe", "secure_config_props", fakeSecureDataExpected); expect(writeFileSyncSpy).toHaveBeenCalledTimes(1); @@ -731,7 +717,7 @@ describe("Configuration Secure command handler", () => { }); it("should not invoke auth handler if auth handler is for different token type", async () => { - const eco = lodash.cloneDeep(expectedConfigObjectWithToken); + const eco = lodash.cloneDeep(expectedProjConfigObjectWithToken); readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); existsSyncSpy.mockReturnValueOnce(false).mockReturnValueOnce(true).mockReturnValue(false); // Only the project config exists @@ -754,7 +740,7 @@ describe("Configuration Secure command handler", () => { const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); delete fakeSecureDataExpectedJson[fakeProjPath]; fakeSecureDataExpectedJson[fakeProjPath] = { - "profiles.base.properties.tokenValue": "fakePromptingData" + "profiles.project_base.properties.tokenValue": "fakePromptingData" }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -762,12 +748,12 @@ describe("Configuration Secure command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.tokenValue; // Delete the secret + delete compObj.profiles.project_base.properties.tokenValue; // Delete the secret expect(keytarDeletePasswordSpy).toHaveBeenCalledTimes(process.platform === "win32" ? 4 : 3); expect(keytarGetPasswordSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(1); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(1); + expect(readPromptSpy).toHaveBeenCalledTimes(1); expect(mockAuthHandlerApi.sessionLogin).toHaveBeenCalledTimes(0); expect(keytarSetPasswordSpy).toHaveBeenCalledWith("Zowe", "secure_config_props", fakeSecureDataExpected); expect(writeFileSyncSpy).toHaveBeenCalledTimes(1); @@ -775,7 +761,7 @@ describe("Configuration Secure command handler", () => { }); it("should fail to invoke auth handler if it throws an error", async () => { - const eco = lodash.cloneDeep(expectedConfigObjectWithToken); + const eco = lodash.cloneDeep(expectedProjConfigObjectWithToken); readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); existsSyncSpy.mockReturnValueOnce(false).mockReturnValueOnce(true).mockReturnValue(false); // Only the project config exists @@ -801,7 +787,7 @@ describe("Configuration Secure command handler", () => { expect(caughtError).toBeDefined(); expect(caughtError.message).toContain("Failed to fetch jwtToken"); - expect(promptWithTimeoutSpy).toHaveBeenCalledTimes(2); // User and password + expect(readPromptSpy).toHaveBeenCalledTimes(2); // User and password expect(mockAuthHandlerApi.sessionLogin).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(0); expect(writeFileSyncSpy).toHaveBeenCalledTimes(0); diff --git a/packages/imperative/src/imperative/__tests__/config/cmd/set/set.handler.unit.test.ts b/packages/imperative/src/imperative/__tests__/config/cmd/set/set.handler.unit.test.ts index d060bcb3f4..3185c489a6 100644 --- a/packages/imperative/src/imperative/__tests__/config/cmd/set/set.handler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/config/cmd/set/set.handler.unit.test.ts @@ -9,14 +9,14 @@ * */ -import { IHandlerParameters } from "../../../../.."; +import { IHandlerParameters } from "../../../../../cmd"; import { Config } from "../../../../../config/src/Config"; import { IConfigOpts } from "../../../../../config"; import { ImperativeConfig } from "../../../../../utilities"; import { IImperativeConfig } from "../../../../src/doc/IImperativeConfig"; import { ICredentialManagerInit } from "../../../../../security/src/doc/ICredentialManagerInit"; import { CredentialManagerFactory } from "../../../../../security"; -import { expectedConfigObject, expectedUserConfigObject } from +import { expectedGlobalConfigObject, expectedGlobalUserConfigObject, expectedProjectConfigObject, expectedProjectUserConfigObject } from "../../../../../../__tests__/__integration__/imperative/__tests__/__integration__/cli/config/__resources__/expectedObjects"; import SetHandler from "../../../../src/config/cmd/set/set.handler"; import * as config from "../../../../../../__tests__/__integration__/imperative/src/imperative"; @@ -25,6 +25,7 @@ import * as path from "path"; import * as lodash from "lodash"; import * as fs from "fs"; import { setupConfigToLoad } from "../../../../../../__tests__/src/TestUtil"; +import { EventOperator, EventUtils } from "../../../../../events"; const getIHandlerParametersObject = (): IHandlerParameters => { const x: any = { @@ -60,16 +61,14 @@ const credentialManager: ICredentialManagerInit = { const fakeConfig = config as IImperativeConfig; const fakeProjPath = path.join(__dirname, "fakeapp.config.json"); -const fakeSchemaPath = path.join(__dirname, "fakeapp.schema.json"); const fakeProjUserPath = path.join(__dirname, "fakeapp.config.user.json"); -const fakeGblProjPath = path.join(__dirname, ".fakeapp", "fakeapp.config.json"); -const fakeGblSchemaPath = path.join(__dirname, ".fakeapp", "fakeapp.schema.json"); -const fakeGblProjUserPath = path.join(__dirname, ".fakeapp", "fakeapp.config.user.json"); +const fakeGlobalPath = path.join(__dirname, ".fakeapp", "fakeapp.config.json"); +const fakeGlobalUserPath = path.join(__dirname, ".fakeapp", "fakeapp.config.user.json"); const fakeUnrelatedPath = path.join(__dirname, "anotherapp.config.json"); const fakeSecureDataJson: any = {}; -fakeSecureDataJson[fakeProjPath] = {"profiles.base.properties.secret": "fakeSecureValue"}; -fakeSecureDataJson[fakeGblProjPath] = {"profiles.base.properties.secret": "fakeSecureValue"}; +fakeSecureDataJson[fakeProjPath] = {"profiles.project_base.properties.secret": "fakeSecureValue"}; +fakeSecureDataJson[fakeGlobalPath] = {"profiles.global_base.properties.secret": "fakeSecureValue"}; const fakeSecureData = Buffer.from(JSON.stringify(fakeSecureDataJson)).toString("base64"); @@ -85,12 +84,12 @@ describe("Configuration Set command handler", () => { const configOpts: IConfigOpts = { vault: { - load: ((k: string): Promise => { + load: (k: string): Promise => { return CredentialManagerFactory.manager.load(k, true); - }), - save: ((k: string, v: any): Promise => { + }, + save: (k: string, v: any): Promise => { return CredentialManagerFactory.manager.save(k, v); - }) + } } }; @@ -115,6 +114,9 @@ describe("Configuration Set command handler", () => { keytarGetPasswordSpy = jest.spyOn(keytar, "getPassword"); keytarSetPasswordSpy = jest.spyOn(keytar, "setPassword"); keytarDeletePasswordSpy = jest.spyOn(keytar, "deletePassword"); + + jest.spyOn(EventUtils, "validateAppName").mockImplementation(jest.fn()); + jest.spyOn(EventOperator, "getZoweProcessor").mockReturnValue({emitZoweEvent: jest.fn()} as any); }); afterEach( () => { @@ -140,7 +142,7 @@ describe("Configuration Set command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedConfigObject); + const eco = lodash.cloneDeep(expectedProjectConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); @@ -164,7 +166,7 @@ describe("Configuration Set command handler", () => { delete fakeSecureDataExpectedJson[fakeProjPath]; fakeSecureDataExpectedJson[fakeProjPath] = { "profiles.secured.properties.testProperty": "aSecuredTestProperty", - "profiles.base.properties.secret": "fakeSecureValue" + "profiles.project_base.properties.secret": "fakeSecureValue" }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -172,7 +174,7 @@ describe("Configuration Set command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles.project_base.properties.secret; // Delete the secret delete compObj.profiles.secured.properties.testProperty; // Delete the new secret if (process.platform === "win32") { @@ -187,7 +189,7 @@ describe("Configuration Set command handler", () => { expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeProjPath, JSON.stringify(compObj, null, 4)); // Config }); - it("should secure a property and add it to the user configuration", async () => { + it("should secure a property and add it to the project user configuration", async () => { const handler = new SetHandler(); const params = getIHandlerParametersObject(); @@ -206,7 +208,7 @@ describe("Configuration Set command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedUserConfigObject); + const eco = lodash.cloneDeep(expectedProjectUserConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); @@ -236,7 +238,7 @@ describe("Configuration Set command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles.project_base.properties.secret; // Delete the secret delete compObj.profiles.secured.properties.testProperty; // Delete the new secret if (process.platform === "win32") { @@ -251,7 +253,7 @@ describe("Configuration Set command handler", () => { expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeProjUserPath, JSON.stringify(compObj, null, 4)); // Config }); - it("should secure a property and add it to the global project configuration", async () => { + it("should secure a property and add it to the global configuration", async () => { const handler = new SetHandler(); const params = getIHandlerParametersObject(); @@ -270,14 +272,14 @@ describe("Configuration Set command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedConfigObject); + const eco = lodash.cloneDeep(expectedGlobalConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); existsSyncSpy.mockReturnValueOnce(false).mockReturnValueOnce(false).mockReturnValueOnce(false) .mockReturnValueOnce(true).mockReturnValue(false); // Only the global project config exists writeFileSyncSpy.mockImplementation(); - searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath); // Give search something to return + searchSpy.mockReturnValueOnce(fakeGlobalUserPath).mockReturnValueOnce(fakeGlobalPath); // Give search something to return await setupConfigToLoad(undefined, configOpts); // Setup the config @@ -292,10 +294,10 @@ describe("Configuration Set command handler", () => { await handler.process(params); const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); - delete fakeSecureDataExpectedJson[fakeGblProjPath]; - fakeSecureDataExpectedJson[fakeGblProjPath] = { + delete fakeSecureDataExpectedJson[fakeGlobalPath]; + fakeSecureDataExpectedJson[fakeGlobalPath] = { "profiles.secured.properties.testProperty": "aSecuredTestProperty", - "profiles.base.properties.secret": "fakeSecureValue" + "profiles.global_base.properties.secret": "fakeSecureValue" }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -303,7 +305,7 @@ describe("Configuration Set command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles.global_base.properties.secret; // Delete the secret delete compObj.profiles.secured.properties.testProperty; // Delete the new secret if (process.platform === "win32") { @@ -315,7 +317,7 @@ describe("Configuration Set command handler", () => { expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledWith("Zowe", "secure_config_props", fakeSecureDataExpected); expect(writeFileSyncSpy).toHaveBeenCalledTimes(1); - expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeGblProjPath, JSON.stringify(compObj, null, 4)); // Config + expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeGlobalPath, JSON.stringify(compObj, null, 4)); // Config }); it("should secure a property and add it to the global user configuration", async () => { @@ -337,14 +339,14 @@ describe("Configuration Set command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedUserConfigObject); + const eco = lodash.cloneDeep(expectedGlobalUserConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); existsSyncSpy.mockReturnValueOnce(false).mockReturnValueOnce(false) .mockReturnValueOnce(true).mockReturnValue(false); // Only the global user project config exists writeFileSyncSpy.mockImplementation(); - searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath); // Give search something to return + searchSpy.mockReturnValueOnce(fakeGlobalUserPath).mockReturnValueOnce(fakeGlobalPath); // Give search something to return await setupConfigToLoad(undefined, configOpts); // Setup the config @@ -359,7 +361,7 @@ describe("Configuration Set command handler", () => { await handler.process(params); const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); - fakeSecureDataExpectedJson[fakeGblProjUserPath] = { + fakeSecureDataExpectedJson[fakeGlobalUserPath] = { "profiles.secured.properties.testProperty": "aSecuredTestProperty" }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -368,7 +370,7 @@ describe("Configuration Set command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; // Delete the secret + delete compObj.profiles.global_base.properties.secret; // Delete the secret delete compObj.profiles.secured.properties.testProperty; // Delete the new secret if (process.platform === "win32") { @@ -380,7 +382,7 @@ describe("Configuration Set command handler", () => { expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledWith("Zowe", "secure_config_props", fakeSecureDataExpected); expect(writeFileSyncSpy).toHaveBeenCalledTimes(1); - expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeGblProjUserPath, JSON.stringify(compObj, null, 4)); // Config + expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeGlobalUserPath, JSON.stringify(compObj, null, 4)); // Config }); it("should allow you to define an insecure property and add it to the project configuration", async () => { @@ -390,7 +392,7 @@ describe("Configuration Set command handler", () => { params.arguments.userConfig = false; params.arguments.globalConfig = false; params.arguments.secure = false; - params.arguments.property = "profiles.base.properties.secret"; + params.arguments.property = "profiles.project_base.properties.secret"; params.arguments.value = "anUnsecuredTestProperty"; // Start doing fs mocks @@ -402,7 +404,7 @@ describe("Configuration Set command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedConfigObject); + const eco = lodash.cloneDeep(expectedProjectConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); @@ -443,14 +445,14 @@ describe("Configuration Set command handler", () => { expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeProjPath, JSON.stringify(compObj, null, 4)); // Config }); - it("should allow you to define an insecure property and add it to the user configuration", async () => { + it("should allow you to define an insecure property and add it to the project user configuration", async () => { const handler = new SetHandler(); const params = getIHandlerParametersObject(); params.arguments.userConfig = true; params.arguments.globalConfig = false; params.arguments.secure = false; - params.arguments.property = "profiles.base.properties.secret"; + params.arguments.property = "profiles.project_base.properties.secret"; params.arguments.value = "anUnsecuredTestProperty"; // Start doing fs mocks @@ -462,13 +464,13 @@ describe("Configuration Set command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedUserConfigObject); + const eco = lodash.cloneDeep(expectedProjectUserConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); existsSyncSpy.mockReturnValueOnce(true).mockReturnValue(false); // Only the global user project config exists writeFileSyncSpy.mockImplementation(); - searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath); // Give search something to return + searchSpy.mockReturnValueOnce(fakeGlobalUserPath).mockReturnValueOnce(fakeGlobalPath); // Give search something to return await setupConfigToLoad(undefined, configOpts); // Setup the config @@ -499,17 +501,17 @@ describe("Configuration Set command handler", () => { expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledWith("Zowe", "secure_config_props", fakeSecureDataExpected); expect(writeFileSyncSpy).toHaveBeenCalledTimes(1); - expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeProjUserPath, JSON.stringify(compObj, null, 4)); // Config + expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeGlobalUserPath, JSON.stringify(compObj, null, 4)); // Config }); - it("should allow you to define an insecure property and add it to the global project configuration", async () => { + it("should allow you to define an insecure property and add it to the global configuration", async () => { const handler = new SetHandler(); const params = getIHandlerParametersObject(); params.arguments.userConfig = false; params.arguments.globalConfig = true; params.arguments.secure = false; - params.arguments.property = "profiles.base.properties.secret"; + params.arguments.property = "profiles.global_base.properties.secret"; params.arguments.value = "anUnsecuredTestProperty"; // Start doing fs mocks @@ -521,14 +523,14 @@ describe("Configuration Set command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedConfigObject); + const eco = lodash.cloneDeep(expectedGlobalConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); existsSyncSpy.mockReturnValueOnce(false).mockReturnValueOnce(false).mockReturnValueOnce(false) .mockReturnValueOnce(true).mockReturnValue(false); // Only the global project config exists writeFileSyncSpy.mockImplementation(); - searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath); // Give search something to return + searchSpy.mockReturnValueOnce(fakeGlobalUserPath).mockReturnValueOnce(fakeGlobalPath); // Give search something to return await setupConfigToLoad(undefined, configOpts); // Setup the config @@ -543,7 +545,7 @@ describe("Configuration Set command handler", () => { await handler.process(params); const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); - delete fakeSecureDataExpectedJson[fakeGblProjPath]; + delete fakeSecureDataExpectedJson[fakeGlobalPath]; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); const compObj: any = {}; @@ -560,7 +562,7 @@ describe("Configuration Set command handler", () => { expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledWith("Zowe", "secure_config_props", fakeSecureDataExpected); expect(writeFileSyncSpy).toHaveBeenCalledTimes(1); - expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeGblProjPath, JSON.stringify(compObj, null, 4)); // Config + expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeGlobalPath, JSON.stringify(compObj, null, 4)); // Config }); it("should allow you to define an insecure property and add it to the global user configuration", async () => { @@ -570,7 +572,7 @@ describe("Configuration Set command handler", () => { params.arguments.userConfig = true; params.arguments.globalConfig = true; params.arguments.secure = false; - params.arguments.property = "profiles.base.properties.secret"; + params.arguments.property = "profiles.global_base.properties.secret"; params.arguments.value = "anUnsecuredTestProperty"; // Start doing fs mocks @@ -582,14 +584,14 @@ describe("Configuration Set command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedUserConfigObject); + const eco = lodash.cloneDeep(expectedGlobalUserConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); existsSyncSpy.mockReturnValueOnce(false).mockReturnValueOnce(false) .mockReturnValueOnce(true).mockReturnValue(false); // Only the global user project config exists writeFileSyncSpy.mockImplementation(); - searchSpy.mockReturnValueOnce(fakeProjUserPath).mockReturnValueOnce(fakeProjPath); // Give search something to return + searchSpy.mockReturnValueOnce(fakeGlobalUserPath).mockReturnValueOnce(fakeGlobalPath); // Give search something to return await setupConfigToLoad(undefined, configOpts); // Setup the config @@ -620,7 +622,7 @@ describe("Configuration Set command handler", () => { expect(keytarSetPasswordSpy).toHaveBeenCalledTimes(1); expect(keytarSetPasswordSpy).toHaveBeenCalledWith("Zowe", "secure_config_props", fakeSecureDataExpected); expect(writeFileSyncSpy).toHaveBeenCalledTimes(1); - expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeGblProjUserPath, JSON.stringify(compObj, null, 4)); // Config + expect(writeFileSyncSpy).toHaveBeenNthCalledWith(1, fakeGlobalUserPath, JSON.stringify(compObj, null, 4)); // Config }); it("should allow you to define an insecure property and add it to the project configuration while keeping other secure props", async () => { @@ -630,11 +632,11 @@ describe("Configuration Set command handler", () => { params.arguments.userConfig = false; params.arguments.globalConfig = false; params.arguments.secure = false; - params.arguments.property = "profiles.base.properties.secret"; + params.arguments.property = "profiles.project_base.properties.secret"; params.arguments.value = "anUnsecuredTestProperty"; const testKeystoreJson = lodash.cloneDeep(fakeSecureDataJson); - testKeystoreJson[fakeUnrelatedPath] = {"profiles.base.properties.secret": "anotherFakeSecureValue"}; + testKeystoreJson[fakeUnrelatedPath] = {"profiles.project_base.properties.secret": "anotherFakeSecureValue"}; const testKeystore = Buffer.from(JSON.stringify(testKeystoreJson)).toString("base64"); @@ -647,7 +649,7 @@ describe("Configuration Set command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedConfigObject); + const eco = lodash.cloneDeep(expectedProjectConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); @@ -669,7 +671,7 @@ describe("Configuration Set command handler", () => { const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); delete fakeSecureDataExpectedJson[fakeProjPath]; - fakeSecureDataExpectedJson[fakeUnrelatedPath] = {"profiles.base.properties.secret": "anotherFakeSecureValue"}; + fakeSecureDataExpectedJson[fakeUnrelatedPath] = {"profiles.project_base.properties.secret": "anotherFakeSecureValue"}; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); const compObj: any = {}; @@ -711,7 +713,7 @@ describe("Configuration Set command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedConfigObject); + const eco = lodash.cloneDeep(expectedProjectConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); @@ -735,7 +737,7 @@ describe("Configuration Set command handler", () => { const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); delete fakeSecureDataExpectedJson[fakeProjPath]; fakeSecureDataExpectedJson[fakeProjPath] = { - "profiles.base.properties.secret": "fakeSecureValue" + "profiles.project_base.properties.secret": "fakeSecureValue" }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -743,7 +745,7 @@ describe("Configuration Set command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; + delete compObj.profiles.project_base.properties.secret; if (process.platform === "win32") { expect(keytarDeletePasswordSpy).toHaveBeenCalledTimes(4); @@ -766,7 +768,7 @@ describe("Configuration Set command handler", () => { params.arguments.userConfig = false; params.arguments.globalConfig = false; params.arguments.secure = null; - params.arguments.property = "profiles.base.properties.secret"; + params.arguments.property = "profiles.project_base.properties.secret"; params.arguments.value = "aSecuredTestProperty"; // Start doing fs mocks @@ -778,7 +780,7 @@ describe("Configuration Set command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedConfigObject); + const eco = lodash.cloneDeep(expectedProjectConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); @@ -801,7 +803,7 @@ describe("Configuration Set command handler", () => { const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); delete fakeSecureDataExpectedJson[fakeProjPath]; fakeSecureDataExpectedJson[fakeProjPath] = { - "profiles.base.properties.secret": "aSecuredTestProperty" + "profiles.project_base.properties.secret": "aSecuredTestProperty" }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -809,7 +811,7 @@ describe("Configuration Set command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; + delete compObj.profiles.project_base.properties.secret; if (process.platform === "win32") { expect(keytarDeletePasswordSpy).toHaveBeenCalledTimes(4); @@ -842,7 +844,7 @@ describe("Configuration Set command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedConfigObject); + const eco = lodash.cloneDeep(expectedProjectConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); @@ -866,7 +868,7 @@ describe("Configuration Set command handler", () => { const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); delete fakeSecureDataExpectedJson[fakeProjPath]; fakeSecureDataExpectedJson[fakeProjPath] = { - "profiles.base.properties.secret": "fakeSecureValue" + "profiles.project_base.properties.secret": "fakeSecureValue" }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -874,7 +876,7 @@ describe("Configuration Set command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; + delete compObj.profiles.project_base.properties.secret; if (process.platform === "win32") { expect(keytarDeletePasswordSpy).toHaveBeenCalledTimes(4); @@ -896,7 +898,7 @@ describe("Configuration Set command handler", () => { params.arguments.globalConfig = false; params.arguments.secure = true; params.arguments.json = true; - params.arguments.property = "profiles.base.properties.secret"; + params.arguments.property = "profiles.project_base.properties.secret"; params.arguments.value = '{"fakeProp":"fakeVal"}'; // Start doing fs mocks @@ -908,7 +910,7 @@ describe("Configuration Set command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedConfigObject); + const eco = lodash.cloneDeep(expectedProjectConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); @@ -931,7 +933,7 @@ describe("Configuration Set command handler", () => { const fakeSecureDataExpectedJson: { [key: string]: any} = lodash.cloneDeep(fakeSecureDataJson); delete fakeSecureDataExpectedJson[fakeProjPath]; fakeSecureDataExpectedJson[fakeProjPath] = { - "profiles.base.properties.secret": {"fakeProp": "fakeVal"} + "profiles.project_base.properties.secret": {"fakeProp": "fakeVal"} }; const fakeSecureDataExpected = Buffer.from(JSON.stringify(fakeSecureDataExpectedJson)).toString("base64"); @@ -940,7 +942,7 @@ describe("Configuration Set command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; + delete compObj.profiles.project_base.properties.secret; if (process.platform === "win32") { expect(keytarDeletePasswordSpy).toHaveBeenCalledTimes(4); @@ -962,7 +964,7 @@ describe("Configuration Set command handler", () => { params.arguments.globalConfig = false; params.arguments.secure = true; params.arguments.json = true; - params.arguments.property = "profiles.base.properties.secret"; + params.arguments.property = "profiles.project_base.properties.secret"; params.arguments.value = '{"fakeProp"::"fakeVal"}'; // Start doing fs mocks @@ -974,7 +976,7 @@ describe("Configuration Set command handler", () => { writeFileSyncSpy = jest.spyOn(fs, "writeFileSync"); existsSyncSpy = jest.spyOn(fs, "existsSync"); - const eco = lodash.cloneDeep(expectedConfigObject); + const eco = lodash.cloneDeep(expectedProjectConfigObject); eco.$schema = "./fakeapp.schema.json"; readFileSyncSpy.mockReturnValueOnce(JSON.stringify(eco)); @@ -1003,7 +1005,7 @@ describe("Configuration Set command handler", () => { // Make changes to satisfy what would be stored on the JSON compObj.$schema = "./fakeapp.schema.json"; // Fill in the name of the schema file, and make it first lodash.merge(compObj, ImperativeConfig.instance.config.properties); // Add the properties from the config - delete compObj.profiles.base.properties.secret; + delete compObj.profiles.project_base.properties.secret; expect(error).toBeDefined(); expect(error.message).toContain("could not parse JSON value"); diff --git a/packages/imperative/src/imperative/__tests__/config/cmd/update-schema/updateSchema.handler.unit.test.ts b/packages/imperative/src/imperative/__tests__/config/cmd/update-schema/updateSchema.handler.unit.test.ts index 650539f2a8..9cf0375c11 100644 --- a/packages/imperative/src/imperative/__tests__/config/cmd/update-schema/updateSchema.handler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/config/cmd/update-schema/updateSchema.handler.unit.test.ts @@ -123,7 +123,7 @@ describe("Configuration Update-Schema command handler", () => { loadedConfigMock.mockReturnValueOnce(undefined); let caughtError = null; try { - await (new UpdateSchemasHandler()).process(handlerParms); + await new UpdateSchemasHandler().process(handlerParms); } catch (err) { caughtError = err.message; } @@ -134,7 +134,7 @@ describe("Configuration Update-Schema command handler", () => { }); it("should print schema JSON", async () => { - await (new UpdateSchemasHandler()).process(handlerParms); + await new UpdateSchemasHandler().process(handlerParms); expect(dataObj).toMatchObject(expectedDataObj); expect(logText).toEqual(`Configuration files found: ${Object.keys(expectedDataObj).length}`); expect(formatObj).toMatchObject({ diff --git a/packages/imperative/src/imperative/__tests__/handlers/DefaultRootCommandHandler.unit.test.ts b/packages/imperative/src/imperative/__tests__/handlers/DefaultRootCommandHandler.unit.test.ts index b98317b2aa..f61dbf32f5 100644 --- a/packages/imperative/src/imperative/__tests__/handlers/DefaultRootCommandHandler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/handlers/DefaultRootCommandHandler.unit.test.ts @@ -13,7 +13,8 @@ jest.mock("../../../utilities/src/ImperativeConfig"); jest.mock("../../../imperative/src/Imperative"); import { TestLogger } from "../../../../__tests__/src/TestLogger"; -import { ICommandDefinition, CommandResponse, CommandPreparer, ICommandHandler } from "../../../cmd"; +import { CommandPreparer } from "../../../cmd/src/CommandPreparer"; +import { ICommandDefinition, CommandResponse, ICommandHandler } from "../../../cmd"; import { ICommandHandlerRequire } from "../../../cmd/src/doc/handler/ICommandHandlerRequire"; import { ImperativeConfig } from "../../../utilities/src/ImperativeConfig"; @@ -115,7 +116,6 @@ describe("Default Root Command Handler", () => { arguments: {_: [], $0: ""}, definition: prepared.children?.[0].children?.[0] as any, fullDefinition: prepared, - profiles: undefined as any, positionals: [], stdin: process.stdin }); @@ -135,7 +135,6 @@ describe("Default Root Command Handler", () => { arguments: {_: [], $0: "", availableCommands: true}, definition: MULTIPLE_GROUPS, fullDefinition: MULTIPLE_GROUPS, - profiles: undefined as any, positionals: [], stdin: process.stdin }); @@ -158,7 +157,6 @@ describe("Default Root Command Handler", () => { arguments: {_: [], $0: "", version: true}, definition: MULTIPLE_GROUPS.children?.[0].children?.[0] as any, fullDefinition: MULTIPLE_GROUPS, - profiles: undefined as any, positionals: [], stdin: process.stdin }); diff --git a/packages/imperative/src/imperative/__tests__/handlers/__snapshots__/DefaultRootCommandHandler.unit.test.ts.snap b/packages/imperative/src/imperative/__tests__/handlers/__snapshots__/DefaultRootCommandHandler.unit.test.ts.snap index 69b79cfc2c..13319de429 100644 --- a/packages/imperative/src/imperative/__tests__/handlers/__snapshots__/DefaultRootCommandHandler.unit.test.ts.snap +++ b/packages/imperative/src/imperative/__tests__/handlers/__snapshots__/DefaultRootCommandHandler.unit.test.ts.snap @@ -280,22 +280,62 @@ exports[`Default Root Command Handler should display the version if --version is Object { "data": Object { "version": 10000, + "zoweVersion": "V99", }, "error": undefined, "exitCode": 0, - "message": "Version displayed", + "message": "Version(s) displayed", "stderr": Object { "data": Array [], "type": "Buffer", }, "stdout": Object { "data": Array [ + 67, + 76, + 73, + 32, + 86, + 101, + 114, + 115, + 105, + 111, + 110, + 58, + 32, 49, 48, 48, 48, 48, 10, + 90, + 111, + 119, + 101, + 32, + 82, + 101, + 108, + 101, + 97, + 115, + 101, + 32, + 86, + 101, + 114, + 115, + 105, + 111, + 110, + 58, + 32, + 86, + 57, + 57, + 10, ], "type": "Buffer", }, diff --git a/packages/imperative/src/imperative/__tests__/plugins/PluginManagementFacility.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/PluginManagementFacility.unit.test.ts index 09bf320951..35dd35707e 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/PluginManagementFacility.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/PluginManagementFacility.unit.test.ts @@ -87,7 +87,6 @@ describe("Plugin Management Facility", () => { pluginAliases: goodPluginAliases, pluginSummary: goodPluginSummary, rootCommandDescription: "imperative sample plugin", - pluginHealthCheck: "./lib/sample-plugin/healthCheck.handler", // TODO: remove in V3, when pluginHealthCheck is removed definitions: [ { name: "foo", @@ -215,6 +214,7 @@ describe("Plugin Management Facility", () => { expect(UpdateImpConfig.addCmdGrp).toHaveBeenCalledWith({ name: "plugins", type: "group", + summary: "Install and manage plug-ins", description: "Install and manage plug-ins.", children: [ installDef, @@ -234,8 +234,8 @@ describe("Plugin Management Facility", () => { const knownOverridePluginNm = CredentialManagerOverride.getKnownCredMgrs()[1].credMgrPluginName as string; const mockInstalledPlugins: IPluginJson = { - firstPlugin: {package: "1", registry: "1", version: "1"}, - secondPlugin: {package: "2", registry: "2", version: "2"} + firstPlugin: {package: "1", location: "1", version: "1"}, + secondPlugin: {package: "2", location: "2", version: "2"} }; const loadPluginCfgPropsReal: any = PMF.loadPluginCfgProps; const loadPluginCfgPropsMock = jest.fn(); @@ -734,48 +734,6 @@ describe("Plugin Management Facility", () => { "The plugin defines no commands and overrides no framework components."); }); - // TODO: remove this test in V3, when pluginHealthCheck is removed - it("should not record warning if pluginHealthCheck property does not exist", () => { - // remove pluginHealthCheck property from config - badPluginConfig = JSON.parse(JSON.stringify(basePluginConfig)); - // eslint-disable-next-line deprecation/deprecation - delete badPluginConfig.pluginHealthCheck; - badPluginCfgProps = JSON.parse(JSON.stringify(basePluginCfgProps)); - badPluginCfgProps.impConfig = badPluginConfig; - - // Ensure we get to the function that we want to validate - mockConflictNmOrAlias.mockReturnValueOnce({ hasConflict: false }); - mockAreVersionsCompatible.mockReturnValueOnce(true); - - isValid = PMF.validatePlugin(badPluginCfgProps, basePluginCmdDef); - - // missing healthCheck is just a warning, so we succeed - expect(isValid).toBe(true); - - // we no longer report any error about missing pluginHealthCheck property - expect(pluginIssues.getIssueListForPlugin(pluginName).length).toBe(0); - }); - - // TODO: remove this test in V3, when pluginHealthCheck is removed - it("should not record error if pluginHealthCheck file does not exist", () => { - // set pluginHealthCheck property to a bogus file - badPluginConfig = JSON.parse(JSON.stringify(basePluginConfig)); - // eslint-disable-next-line deprecation/deprecation - badPluginConfig.pluginHealthCheck = "./This/File/Does/Not/Exist"; - badPluginCfgProps = JSON.parse(JSON.stringify(basePluginCfgProps)); - badPluginCfgProps.impConfig = badPluginConfig; - - // Ensure we get to the function that we want to validate - mockConflictNmOrAlias.mockReturnValueOnce({ hasConflict: false }); - mockAreVersionsCompatible.mockReturnValueOnce(true); - - isValid = PMF.validatePlugin(badPluginCfgProps, basePluginCmdDef); - expect(isValid).toBe(true); - - // we no longer report any error about missing pluginHealthCheck file - expect(pluginIssues.getIssueListForPlugin(pluginName).length).toBe(0); - }); - it("should record error when ConfigurationValidator throws an exception", () => { // Ensure we get to the function that we want to validate PMF.conflictingNameOrAlias = realConflictName; @@ -1944,7 +1902,7 @@ describe("Plugin Management Facility", () => { describe("comparePluginVersionToCli function", () => { beforeEach(() => { PMF.currPluginName = pluginName; - PMF.semver.intersects = jest.fn(); + PMF.semver.satisfies = jest.fn(); // impCfg.getCliCmdName is a getter of a property, so mock the property Object.defineProperty(impCfg, "cliCmdName", { @@ -1956,7 +1914,7 @@ describe("Plugin Management Facility", () => { }); it("should record no issue when version is compatible", () => { - PMF.semver.intersects.mockReturnValueOnce(true); + PMF.semver.satisfies.mockReturnValueOnce(true); PMF.comparePluginVersionToCli(pluginName, "pluginVerVal", "cliVerPropNm", "CliVerVal"); @@ -1964,7 +1922,7 @@ describe("Plugin Management Facility", () => { }); it("should record issue when exception threw by semver", () => { - PMF.semver.intersects.mockImplementationOnce(() => { + PMF.semver.satisfies.mockImplementationOnce(() => { throw new Error("dummy error"); }); diff --git a/packages/imperative/src/imperative/__tests__/plugins/PluginRequireProvider.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/PluginRequireProvider.unit.test.ts index a1933be968..4daeb3af50 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/PluginRequireProvider.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/PluginRequireProvider.unit.test.ts @@ -429,8 +429,7 @@ describe("PluginRequireProvider", () => { try { // The return should be the main module as that is what the module loader does. - // eslint-disable-next-line deprecation/deprecation - expect(modulePrototype.require.call(thisObject, module, testRequireIndicator)).toBe(process.mainModule); + expect(modulePrototype.require.call(thisObject, module, testRequireIndicator)).toBe(undefined); // Expect that the require was just called with the module expect(mockedRequire).toHaveBeenCalledTimes(1); @@ -443,8 +442,7 @@ describe("PluginRequireProvider", () => { const submodule = `${module}/submodule/import`; expect(modulePrototype.require.call( thisObject, submodule, testRequireIndicator - // eslint-disable-next-line deprecation/deprecation - )).toBe(process.mainModule); + )).toBe(undefined); // Expect that the require was just called with the submodule expect(mockedRequire).toHaveBeenCalledTimes(1); @@ -477,8 +475,7 @@ describe("PluginRequireProvider", () => { try { expect(modulePrototype.require.call( thisObject, module, testRequireIndicator - // eslint-disable-next-line deprecation/deprecation - )).toBe(process.mainModule); + )).toBe(undefined); expect(mockedRequire).toHaveBeenCalledTimes(1); expect(mockedRequire).toHaveBeenCalledWith("./", testRequireIndicator); @@ -509,8 +506,7 @@ describe("PluginRequireProvider", () => { try { expect(modulePrototype.require.call( thisObject, module + submoduleImport, testRequireIndicator - // eslint-disable-next-line deprecation/deprecation - )).toBe(process.mainModule); + )).toBe(undefined); expect(mockedRequire).toHaveBeenCalledTimes(1); expect(mockedRequire).toHaveBeenCalledWith(packageRoot + submoduleImport, testRequireIndicator); diff --git a/packages/imperative/src/imperative/__tests__/plugins/cmd/install/install.handler.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/cmd/install/install.handler.unit.test.ts index 5f684e74bb..1cbba51d8a 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/cmd/install/install.handler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/cmd/install/install.handler.unit.test.ts @@ -51,8 +51,9 @@ import { Logger } from "../../../../../logger"; import { readFileSync, writeFileSync } from "jsonfile"; import { PMFConstants } from "../../../../src/plugins/utilities/PMFConstants"; import { TextUtils } from "../../../../../utilities"; -import { getRegistry, npmLogin } from "../../../../src/plugins/utilities/NpmFunctions"; +import { getRegistry, getScopeRegistry, npmLogin } from "../../../../src/plugins/utilities/NpmFunctions"; import * as spawn from "cross-spawn"; +import { IO } from "../../../../../io"; describe("Plugin Management Facility install handler", () => { @@ -60,10 +61,11 @@ describe("Plugin Management Facility install handler", () => { const mocks = { npmLogin: npmLogin as Mock, getRegistry: getRegistry as unknown as Mock, + getScopeRegistry: getScopeRegistry as unknown as Mock, readFileSync: readFileSync as Mock, writeFileSync: writeFileSync as Mock, install: install as unknown as Mock, - runValidatePlugin: runValidatePlugin as unknown as Mock + runValidatePlugin: runValidatePlugin as unknown as Mock, }; // two plugin set of values @@ -180,12 +182,12 @@ describe("Plugin Management Facility install handler", () => { const fileJson: IPluginJson = { a: { package: packageName, - registry: "", + location: "", version: packageVersion }, plugin2: { package: packageName2, - registry: packageRegistry2, + location: packageRegistry2, version: packageVersion2 } }; @@ -379,5 +381,73 @@ describe("Plugin Management Facility install handler", () => { expect(expectedError.additionalDetails).toContain("Command failed"); expect(expectedError.additionalDetails).toContain("npm"); }); + it("should handle installed plugins via public scope", async () => { + const handler = new InstallHandler(); + + const params = getIHandlerParametersObject(); + params.arguments.plugin = ["@public/sample1"]; + + mocks.getScopeRegistry.mockReturnValueOnce("publicRegistryUrl" as any); + + try { + await handler.process(params); + } catch (e) { + expect(e).toBeUndefined(); + } + + expect(mocks.install).toHaveBeenCalledWith("@public/sample1","publicRegistryUrl"); + }); + it("should handle installed plugins via project/directory", async () => { + const handler = new InstallHandler(); + + const params = getIHandlerParametersObject(); + params.arguments.plugin = ["path/to/dir"]; + jest.spyOn(IO, 'isDir').mockReturnValue(true); + + try{ + await handler.process(params); + } + catch(e){ + expect(e).toBeUndefined(); + } + + expect(mocks.install).toHaveBeenCalledWith("path/to/dir","path/to/dir"); + }); + it("should handle installed plugins via tarball file", async () => { + const handler = new InstallHandler(); + + const params = getIHandlerParametersObject(); + params.arguments.plugin = ["path/to/dir/file.tgz"]; + + try{ + await handler.process(params); + } + catch(e){ + expect(e).toBeUndefined(); + } + + expect(mocks.install).toHaveBeenCalledWith("path/to/dir/file.tgz","path/to/dir/file.tgz"); + }); + it("should handle multiple installed plugins via tarball, director, public registry, and private registry", async () => { + const handler = new InstallHandler(); + + const params = getIHandlerParametersObject(); + params.arguments.plugin = ["@public/sample1","@private/sample1","path/to/dir","path/to/dir/file.tgz"]; + mocks.getScopeRegistry.mockReturnValueOnce("publicRegistryUrl" as any); + mocks.getScopeRegistry.mockReturnValueOnce("privateRegistryUrl" as any); + jest.spyOn(IO, 'isDir').mockReturnValue(true); + + try{ + await handler.process(params); + } + catch(e){ + expect(e).toBeUndefined(); + } + + expect(mocks.install).toHaveBeenCalledWith("@public/sample1","publicRegistryUrl"); + expect(mocks.install).toHaveBeenCalledWith("@private/sample1","privateRegistryUrl"); + expect(mocks.install).toHaveBeenCalledWith("path/to/dir","path/to/dir"); + expect(mocks.install).toHaveBeenCalledWith("path/to/dir/file.tgz","path/to/dir/file.tgz"); + }); }); diff --git a/packages/imperative/src/imperative/__tests__/plugins/cmd/list/__snapshots__/list.handler.unit.test.ts.snap b/packages/imperative/src/imperative/__tests__/plugins/cmd/list/__snapshots__/list.handler.unit.test.ts.snap index a6ae836b85..27e8f5f1d2 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/cmd/list/__snapshots__/list.handler.unit.test.ts.snap +++ b/packages/imperative/src/imperative/__tests__/plugins/cmd/list/__snapshots__/list.handler.unit.test.ts.snap @@ -7,12 +7,12 @@ Installed plugins: -- pluginName: a -- package: a -- version: 22.1.0 - -- registry: http://imperative-npm-registry:4873/ + -- location: http://imperative-npm-registry:4873/ -- pluginName: plugin1 -- package: plugin1 -- version: 2.0.3 - -- registry: http://imperative-npm-registry:4873/ + -- location: http://imperative-npm-registry:4873/ " `; diff --git a/packages/imperative/src/imperative/__tests__/plugins/cmd/list/list.handler.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/cmd/list/list.handler.unit.test.ts index ba6d499011..8db628f52b 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/cmd/list/list.handler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/cmd/list/list.handler.unit.test.ts @@ -90,12 +90,12 @@ describe("Plugin Management Facility list handler", () => { const fileJson: IPluginJson = { plugin1: { package: packageName2, - registry: packageRegistry2, + location: packageRegistry2, version: packageVersion2 }, a: { package: packageName, - registry: packageRegistry, + location: packageRegistry, version: packageVersion } }; @@ -119,12 +119,12 @@ describe("Plugin Management Facility list handler", () => { const fileJson: IPluginJson = { plugin1: { package: packageName2, - registry: packageRegistry2, + location: packageRegistry2, version: packageVersion2 }, a: { package: packageName, - registry: packageRegistry, + location: packageRegistry, version: packageVersion } }; diff --git a/packages/imperative/src/imperative/__tests__/plugins/cmd/uninstall/uninstall.handler.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/cmd/uninstall/uninstall.handler.unit.test.ts index 0c7ebdb07a..84a3592d04 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/cmd/uninstall/uninstall.handler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/cmd/uninstall/uninstall.handler.unit.test.ts @@ -114,12 +114,12 @@ describe("Plugin Management Facility uninstall handler", () => { const fileJson: IPluginJson = { a: { package: packageName, - registry: "", + location: "", version: packageVersion }, plugin1: { package: packageName2, - registry: packageRegistry2, + location: packageRegistry2, version: packageVersion2 } }; diff --git a/packages/imperative/src/imperative/__tests__/plugins/cmd/update/update.handler.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/cmd/update/update.handler.unit.test.ts index 40c914b7ba..d4c29e9c2c 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/cmd/update/update.handler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/cmd/update/update.handler.unit.test.ts @@ -137,12 +137,12 @@ describe("Plugin Management Facility update handler", () => { const fileJson: IPluginJson = { "imperative-sample-plugin": { package: packageName, - registry: packageRegistry, + location: packageRegistry, version: packageVersion }, "plugin1": { package: packageName2, - registry: packageRegistry2, + location: packageRegistry2, version: packageVersion2 } }; @@ -173,7 +173,7 @@ describe("Plugin Management Facility update handler", () => { const fileJson: IPluginJson = { "imperative-sample-plugin": { package: resolveVal, - registry: packageRegistry, + location: packageRegistry, version: "1.0.1" } }; diff --git a/packages/imperative/src/imperative/__tests__/plugins/cmd/validate/validate.handler.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/cmd/validate/validate.handler.unit.test.ts index d2bb50ed5b..b663bcd36e 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/cmd/validate/validate.handler.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/cmd/validate/validate.handler.unit.test.ts @@ -99,7 +99,7 @@ describe("Plugin validate command handler", () => { for (testPlugin in pluginIssues.getInstalledPlugins()){ if (Object.prototype.hasOwnProperty.call(pluginIssues.getInstalledPlugins(), testPlugin)){ - expect(mockDisplayPluginIssues).toBeCalledWith(testPlugin, params.response, false); + expect(mockDisplayPluginIssues).toHaveBeenCalledWith(testPlugin, params.response, false); } } }); diff --git a/packages/imperative/src/imperative/__tests__/plugins/utilities/NpmFunctions.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/utilities/NpmFunctions.unit.test.ts index 41c9021617..a710f1df2c 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/utilities/NpmFunctions.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/utilities/NpmFunctions.unit.test.ts @@ -15,6 +15,7 @@ import * as npmPackageArg from "npm-package-arg"; import * as pacote from "pacote"; import * as npmFunctions from "../../../src/plugins/utilities/NpmFunctions"; import { PMFConstants } from "../../../src/plugins/utilities/PMFConstants"; +import { ExecUtils } from "../../../../utilities"; jest.mock("cross-spawn"); jest.mock("jsonfile"); @@ -75,8 +76,20 @@ describe("NpmFunctions", () => { jest.spyOn(pacote, "manifest").mockResolvedValue(expectedInfo as any); }); - it("should fetch info for package installed from registry", async () => { + it("should fetch info for package installed from registry 1", async () => { const pkgSpec = "@zowe/imperative"; + expect(npmPackageArg(pkgSpec).type).toEqual("range"); + + jest.spyOn(PMFConstants, "instance", "get").mockReturnValueOnce({ + PLUGIN_HOME_LOCATION: "" + } as any); + const actualInfo = await npmFunctions.getPackageInfo(pkgSpec); + expect(actualInfo).toBe(expectedInfo); + expect(jsonfile.readFileSync).toHaveBeenCalledTimes(1); + }); + + it("should fetch info for package installed from registry 2", async () => { + const pkgSpec = "@zowe/imperative@latest"; expect(npmPackageArg(pkgSpec).type).toEqual("tag"); jest.spyOn(PMFConstants, "instance", "get").mockReturnValueOnce({ @@ -122,5 +135,14 @@ describe("NpmFunctions", () => { expect(actualInfo).toBe(expectedInfo); expect(pacote.manifest).toHaveBeenCalledTimes(1); }); + + it("getScopeRegistry() should return registry for 'test' scope", async () => { + const spawnSpy = jest.spyOn(ExecUtils, "spawnAndGetOutput"); + spawnSpy.mockReturnValueOnce("https://test123.com"); + const result = await npmFunctions.getScopeRegistry("test"); + expect(result).toBe("https://test123.com"); + expect(spawnSpy).toHaveBeenCalledTimes(1); + }); + }); }); diff --git a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/install.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/install.unit.test.ts index 6d07a1a448..9fc5aace6a 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/install.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/install.unit.test.ts @@ -59,7 +59,7 @@ import { UpdateImpConfig } from "../../../../src/UpdateImpConfig"; import * as fs from "fs"; import * as path from "path"; import { gt as versionGreaterThan } from "semver"; -import { ProfileInfo } from "../../../../../config"; +import { ConfigUtils } from "../../../../../config"; import mockTypeConfig from "../../__resources__/typeConfiguration"; import { updateExtendersJson } from "../../../../src/plugins/utilities/npm-interface/install"; import { IExtendersJsonOpts } from "../../../../../config/src/doc/IExtenderOpts"; @@ -84,9 +84,9 @@ describe("PMF: Install Interface", () => { UpdateImpConfig_addProfiles: UpdateImpConfig.addProfiles as Mock, path: path as unknown as Mock, ConfigSchema_loadSchema: jest.spyOn(ConfigSchema, "loadSchema"), - ProfileInfo: { - readExtendersJsonFromDisk: jest.spyOn(ProfileInfo, "readExtendersJsonFromDisk"), - writeExtendersJson: jest.spyOn(ProfileInfo, "writeExtendersJson") + ConfigUtils: { + readExtendersJson: jest.spyOn(ConfigUtils, "readExtendersJson"), + writeExtendersJson: jest.spyOn(ConfigUtils, "writeExtendersJson") } }; @@ -110,14 +110,14 @@ describe("PMF: Install Interface", () => { mocks.sync.mockReturnValue("fake_find-up_sync_result" as any); jest.spyOn(path, "dirname").mockReturnValue("fake-dirname"); jest.spyOn(path, "join").mockReturnValue("/fake/join/path"); - mocks.ProfileInfo.readExtendersJsonFromDisk.mockReturnValue({ + mocks.ConfigUtils.readExtendersJson.mockReturnValue({ profileTypes: { "zosmf": { from: ["Zowe CLI"] } } }); - mocks.ProfileInfo.writeExtendersJson.mockImplementation(); + mocks.ConfigUtils.writeExtendersJson.mockImplementation(); mocks.ConfigSchema_loadSchema.mockReturnValue([mockTypeConfig]); mocks.ConfigurationLoader_load.mockReturnValue({ profiles: [mockTypeConfig] } as any); }); @@ -198,7 +198,7 @@ describe("PMF: Install Interface", () => { wasNpmInstallCallValid(packageName, packageRegistry); wasWriteFileSyncCallValid({}, packageName, { package: packageName, - registry: packageRegistry, + location: packageRegistry, version: packageVersion }); }); @@ -214,7 +214,7 @@ describe("PMF: Install Interface", () => { wasNpmInstallCallValid(rootFile, packageRegistry); wasWriteFileSyncCallValid({}, packageName, { package: rootFile, - registry: packageRegistry, + location: packageRegistry, version: packageVersion }); }); @@ -230,7 +230,7 @@ describe("PMF: Install Interface", () => { wasNpmInstallCallValid(rootFile, packageRegistry); wasWriteFileSyncCallValid({}, packageName, { package: rootFile, - registry: packageRegistry, + location: packageRegistry, version: packageVersion }); }); @@ -257,7 +257,7 @@ describe("PMF: Install Interface", () => { wasNpmInstallCallValid(absolutePath, packageRegistry); wasWriteFileSyncCallValid({}, packageName, { package: absolutePath, - registry: packageRegistry, + location: packageRegistry, version: packageVersion }); }); @@ -274,7 +274,7 @@ describe("PMF: Install Interface", () => { wasNpmInstallCallValid(installUrl, packageRegistry); wasWriteFileSyncCallValid({}, packageName, { package: installUrl, - registry: packageRegistry, + location: packageRegistry, version: packageVersion }); }); @@ -288,7 +288,7 @@ describe("PMF: Install Interface", () => { wasNpmInstallCallValid(packageName, packageRegistry, false); wasWriteFileSyncCallValid({}, packageName, { package: packageName, - registry: packageRegistry, + location: packageRegistry, version: packageVersion }); }); @@ -339,7 +339,7 @@ describe("PMF: Install Interface", () => { wasNpmInstallCallValid(semverPackage, packageRegistry); wasWriteFileSyncCallValid({}, packageName, { package: packageName, - registry: packageRegistry, + location: packageRegistry, version: semverVersion }); }); @@ -349,7 +349,7 @@ describe("PMF: Install Interface", () => { const oneOldPlugin: IPluginJson = { plugin1: { package: "plugin1", - registry: packageRegistry, + location: packageRegistry, version: "1.2.3" } }; @@ -368,7 +368,7 @@ describe("PMF: Install Interface", () => { wasNpmInstallCallValid(packageName, packageRegistry); wasWriteFileSyncCallValid(oneOldPlugin, packageName, { package: packageName, - registry: packageRegistry, + location: packageRegistry, version: packageVersion }); }); @@ -383,7 +383,7 @@ describe("PMF: Install Interface", () => { const oneOldPlugin: IPluginJson = { plugin1: { package: "plugin1", - registry: packageRegistry, + location: packageRegistry, version: "1.2.3" } }; @@ -405,7 +405,7 @@ describe("PMF: Install Interface", () => { mocks.readFileSync.mockReturnValue(oneOldPlugin as any); if (opts.lastVersion) { - mocks.ProfileInfo.readExtendersJsonFromDisk.mockReturnValueOnce({ + mocks.ConfigUtils.readExtendersJson.mockReturnValueOnce({ profileTypes: { "test-type": { from: [oneOldPlugin.plugin1.package], @@ -426,9 +426,9 @@ describe("PMF: Install Interface", () => { if (opts.version && opts.lastVersion) { if (versionGreaterThan(opts.version, opts.lastVersion)) { - expect(mocks.ProfileInfo.writeExtendersJson).toHaveBeenCalled(); + expect(mocks.ConfigUtils.writeExtendersJson).toHaveBeenCalled(); } else { - expect(mocks.ProfileInfo.writeExtendersJson).not.toHaveBeenCalled(); + expect(mocks.ConfigUtils.writeExtendersJson).not.toHaveBeenCalled(); } } }; diff --git a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/uninstall.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/uninstall.unit.test.ts index 1a0230e89f..49714cfa17 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/uninstall.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/uninstall.unit.test.ts @@ -30,7 +30,7 @@ import { PMFConstants } from "../../../../src/plugins/utilities/PMFConstants"; import { readFileSync, writeFileSync } from "jsonfile"; import { findNpmOnPath } from "../../../../src/plugins/utilities/NpmFunctions"; import { uninstall } from "../../../../src/plugins/utilities/npm-interface"; -import { ConfigSchema, ProfileInfo } from "../../../../../config"; +import { ConfigSchema, ConfigUtils } from "../../../../../config"; import mockTypeConfig from "../../__resources__/typeConfiguration"; import { ExecUtils } from "../../../../../utilities"; import { IExtendersJsonOpts } from "../../../../../config/src/doc/IExtenderOpts"; @@ -87,10 +87,10 @@ describe("PMF: Uninstall Interface", () => { */ const wasWriteFileSyncCallValid = () => { // Create the object that should be sent to the command. - const expectedObject = { + const expectedObject: IPluginJson = { plugin2: { package: "plugin1", - registry: packageRegistry, + location: packageRegistry, version: "1.2.3" } }; @@ -117,12 +117,12 @@ describe("PMF: Uninstall Interface", () => { const pluginJsonFile: IPluginJson = { a: { package: "a", - registry: packageRegistry, + location: packageRegistry, version: "3.2.1" }, plugin2: { package: "plugin1", - registry: packageRegistry, + location: packageRegistry, version: "1.2.3" } }; @@ -141,12 +141,12 @@ describe("PMF: Uninstall Interface", () => { const pluginJsonFile: IPluginJson = { "imperative-sample-plugin": { package: "C:\\test\\imperative-plugins", - registry: packageRegistry, + location: packageRegistry, version: "1.0.1" }, "plugin2": { package: "plugin1", - registry: packageRegistry, + location: packageRegistry, version: "1.2.3" } }; @@ -187,7 +187,7 @@ describe("PMF: Uninstall Interface", () => { const pluginJsonFile: IPluginJson = { a: { package: "a", - registry: packageRegistry, + location: packageRegistry, version: "3.2.1" } }; @@ -234,12 +234,12 @@ describe("PMF: Uninstall Interface", () => { const pluginJsonFile: IPluginJson = { a: { package: "a", - registry: packageRegistry, + location: packageRegistry, version: "3.2.1" }, plugin2: { package: "plugin1", - registry: packageRegistry, + location: packageRegistry, version: "1.2.3" } }; @@ -248,7 +248,7 @@ describe("PMF: Uninstall Interface", () => { const blockMocks = getBlockMocks(); if (opts.schemaUpdated) { blockMocks.fs.existsSync.mockReturnValueOnce(true); - jest.spyOn(ProfileInfo, "readExtendersJsonFromDisk").mockReturnValue({ + jest.spyOn(ConfigUtils, "readExtendersJson").mockReturnValue({ profileTypes: { "test-type": { from: ["a"], @@ -281,13 +281,13 @@ describe("PMF: Uninstall Interface", () => { describe("updateAndGetRemovedTypes", () => { const getBlockMocks = () => { - const profileInfo = { - readExtendersJsonFromDisk: jest.spyOn(ProfileInfo, "readExtendersJsonFromDisk"), - writeExtendersJson: jest.spyOn(ProfileInfo, "writeExtendersJson").mockImplementation(), + const configUtils = { + readExtendersJson: jest.spyOn(ConfigUtils, "readExtendersJson"), + writeExtendersJson: jest.spyOn(ConfigUtils, "writeExtendersJson").mockImplementation(), }; return { - profileInfo, + configUtils }; }; @@ -296,23 +296,23 @@ describe("PMF: Uninstall Interface", () => { schema?: boolean; }, extendersJson: IExtendersJsonOpts) => { const blockMocks = getBlockMocks(); - blockMocks.profileInfo.readExtendersJsonFromDisk.mockReturnValue(extendersJson); + blockMocks.configUtils.readExtendersJson.mockReturnValue(extendersJson); const hasMultipleSources = extendersJson.profileTypes["some-type"].from.length > 1; const wasLatestSource = extendersJson.profileTypes["some-type"].latestFrom === "aPluginPackage"; const typesToRemove = updateAndGetRemovedTypes("aPluginPackage"); if (shouldUpdate.extJson) { - expect(blockMocks.profileInfo.writeExtendersJson).toHaveBeenCalled(); + expect(blockMocks.configUtils.writeExtendersJson).toHaveBeenCalled(); } else { - expect(blockMocks.profileInfo.writeExtendersJson).not.toHaveBeenCalled(); + expect(blockMocks.configUtils.writeExtendersJson).not.toHaveBeenCalled(); return; } - const newExtendersObj = blockMocks.profileInfo.writeExtendersJson.mock.calls[0][0]; + const newExtendersObj = blockMocks.configUtils.writeExtendersJson.mock.calls[0][0]; if (hasMultipleSources) { - expect(blockMocks.profileInfo.writeExtendersJson).not.toHaveBeenCalledWith( + expect(blockMocks.configUtils.writeExtendersJson).not.toHaveBeenCalledWith( expect.objectContaining({ profileTypes: { "some-type": { @@ -369,7 +369,7 @@ describe("PMF: Uninstall Interface", () => { it("returns an empty list when package does not contribute any profile types", () => { const blockMocks = getBlockMocks(); - blockMocks.profileInfo.readExtendersJsonFromDisk.mockReturnValue({ + blockMocks.configUtils.readExtendersJson.mockReturnValue({ profileTypes: { "some-type": { from: ["anotherPkg"] diff --git a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/update.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/update.unit.test.ts index da2ec64195..f873f360e7 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/update.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/utilities/npm-interface/update.unit.test.ts @@ -76,7 +76,7 @@ describe("PMF: update Interface", () => { const oneOldPlugin: IPluginJson = { plugin1: { package: packageName, - registry: packageRegistry, + location: packageRegistry, version: packageVersion } }; @@ -97,7 +97,7 @@ describe("PMF: update Interface", () => { const oneOldPlugin: IPluginJson = { plugin1: { package: packageName, - registry: packageRegistry, + location: packageRegistry, version: packageVersion } }; diff --git a/packages/imperative/src/imperative/__tests__/plugins/utilities/runValidatePlugin.unit.test.ts b/packages/imperative/src/imperative/__tests__/plugins/utilities/runValidatePlugin.unit.test.ts index bd05515633..d700fa9fae 100644 --- a/packages/imperative/src/imperative/__tests__/plugins/utilities/runValidatePlugin.unit.test.ts +++ b/packages/imperative/src/imperative/__tests__/plugins/utilities/runValidatePlugin.unit.test.ts @@ -31,19 +31,8 @@ const spawnSyncOutput = { }; describe("runValidatePlugin", () => { - // eslint-disable-next-line deprecation/deprecation - const mainModule = process.mainModule; - - beforeEach(() => { - // eslint-disable-next-line deprecation/deprecation - (process.mainModule as any) = { - filename: __filename - }; - }); afterEach(() => { - // eslint-disable-next-line deprecation/deprecation - process.mainModule = mainModule; mocks.spawnSync.mockReset(); }); diff --git a/packages/imperative/src/imperative/__tests__/profiles/handlers/CreateProfilesHandler.unit.test.ts b/packages/imperative/src/imperative/__tests__/profiles/handlers/CreateProfilesHandler.unit.test.ts deleted file mode 100644 index f95db9d1b2..0000000000 --- a/packages/imperative/src/imperative/__tests__/profiles/handlers/CreateProfilesHandler.unit.test.ts +++ /dev/null @@ -1,178 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -jest.mock("../../../src/Imperative"); -jest.mock("../../../../utilities/src/ImperativeConfig"); - -import { IProfileLoaded } from "../../../../profiles"; -import { Imperative } from "../../../src/Imperative"; -import { ImperativeConfig } from "../../../../utilities"; - -const fakeProfileIoError = "Pretend a ProfileIO error occurred"; -const noMsgText = "No message text"; - -let errorText: string = noMsgText; -let logText: string = noMsgText; - -// "Mocked" version of the handler parameters for a create profile command -const createProfileParms: any = { - arguments: { - $0: "zowe", - _: ["profiles", "create", "zosmf-profiles", "newProfName"], - }, - response: { - data: { - setMessage: jest.fn((setMsgArgs) => { - // Nothing - }), - setObj: jest.fn((setObjArgs) => { - // Nothing - }) - }, - console: { - log: jest.fn((msgText) => { - logText = msgText; - }), - error: jest.fn((msgText) => { - errorText = msgText; - }) - } - }, - definition: { - customize: { - profileTypeIdentifier: "fakeType" - } - } -}; - -// "Mocked" profiles -const FAKE_PROFS: IProfileLoaded[] = [ - { - message: "loaded", - type: "fake", - failNotFound: true, - name: "fake1", - profile: { - name: "fake1", - type: "fake", - data: "some data", - info: "some info", - nested: { - data: "nested data" - } - } - }, - { - message: "loaded", - type: "fake", - failNotFound: true, - name: "fake", - profile: { - name: "fake2", - type: "fake", - data: "some data", - info: "some info", - nested: { - data: "nested data" - } - } - } -]; - -const ProfileSaved = { - overwritten: true, - path: "this/is/a/great/path", - profile: { - type: "fakeProfileType" - } -}; - -// "Mocked" version of a crashings imperative API -const impApiMockedCrash = { - profileManager: (args: any) => { - throw new Error(fakeProfileIoError); - }, -}; - -// "Mocked" version of a successful imperative API - done here rather than a manual mock -const impApiMockedOk = { - profileManager: (args: any) => { - return { - getDefaultProfileName: jest.fn(() => { - return "fake1"; - }), - loadAll: jest.fn((loadArgs) => { - return JSON.parse(JSON.stringify(FAKE_PROFS)); - }), - save: jest.fn(() => { - return ProfileSaved; - }), - }; - }, -}; - - -describe("create profile handler", () => { - - // Reset mocks for counters, etc. - beforeEach(() => { - errorText = noMsgText; - logText = noMsgText; - }); - - describe("successful operation", () => { - it("should create a profile", async () => { - /* Pretend that we have **no** team config. - * config is a getter of a property, so mock we the property. - */ - Object.defineProperty(ImperativeConfig.instance, "config", { - configurable: true, - get: jest.fn(() => { - return { - exists: false - }; - }) - }); - - Object.defineProperty(Imperative, "api", { value: impApiMockedOk, configurable: true }); - const parms = Object.assign({}, ...[createProfileParms]); - const handlerReq = require("../../../src/profiles/handlers/CreateProfilesHandler"); - const handler = new handlerReq.default(); - - await handler.process(createProfileParms); - expect(errorText).toBe(noMsgText); - expect(logText).toContain("Review the created profile"); - }); - }); - - describe("error handling", () => { - it("should catch profileIO errors", async () => { - /* Pretend that we have a team config. - * config is a getter of a property, so mock we the property. - */ - Object.defineProperty(ImperativeConfig.instance, "config", { - configurable: true, - get: jest.fn(() => { - return { - exists: true - }; - }) - }); - - Object.defineProperty(Imperative, "api", { value: impApiMockedCrash, configurable: true }); - const handlerReq = require("../../../src/profiles/handlers/CreateProfilesHandler"); - const handler = new handlerReq.default(); - await handler.process(createProfileParms); - expect(errorText).toContain("An error occurred trying to create a profile"); - expect(errorText).toContain(fakeProfileIoError); - }); - }); -}); diff --git a/packages/imperative/src/imperative/__tests__/profiles/handlers/ListProfilesHandler.unit.test.ts b/packages/imperative/src/imperative/__tests__/profiles/handlers/ListProfilesHandler.unit.test.ts deleted file mode 100644 index aafda9c915..0000000000 --- a/packages/imperative/src/imperative/__tests__/profiles/handlers/ListProfilesHandler.unit.test.ts +++ /dev/null @@ -1,243 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -jest.mock("../../../src/Imperative"); -jest.mock("../../../../utilities/src/ImperativeConfig"); - -import { IProfileLoaded } from "../../../../profiles"; -import { Imperative } from "../../../src/Imperative"; -import { ImperativeConfig } from "../../../../utilities"; - -// "Mocked" profiles -const FAKE_PROFS: IProfileLoaded[] = [ - { - message: "loaded", - type: "fake", - failNotFound: true, - name: "fake1", - profile: { - name: "fake1", - type: "fake", - data: "some data", - info: "some info", - nested: { - data: "nested data" - } - } - }, - { - message: "loaded", - type: "fake", - failNotFound: true, - name: "fake", - profile: { - name: "fake2", - type: "fake", - data: "some data", - info: "some info", - nested: { - data: "nested data" - } - } - } -]; - -// "Mocked" version of the imperative API - done here rather than a manual mock -const MockedImperativeAPI = { - profileManager: (args: any) => { - return { - getDefaultProfileName: jest.fn(() => { - return "fake1"; - }), - loadAll: jest.fn((loadArgs) => { - return JSON.parse(JSON.stringify(FAKE_PROFS)); - }) - }; - }, -}; - -// "Mocked" version to thrown an error -const MockedImperativeAPIError = { - profileManager: (args: any) => { - return { - getDefaultProfileName: jest.fn(() => { - return "fake1"; - }), - loadAll: jest.fn((loadArgs) => { - throw new Error("ERROR!"); - }) - }; - }, -}; - -// "Mocked" version of the handler parameters -const HANDLER_PARAMETERS: any = { - arguments: { - $0: "bright", - _: ["zos-jobs", "submit", "data-set"], - }, - response: { - data: { - setMessage: jest.fn((setMsgArgs) => { - // Nothing - }), - setObj: jest.fn((setObjArgs) => { - // Nothing - }) - }, - console: { - log: jest.fn((logs) => { - // Nothing - }), - error: jest.fn((errors) => { - // Nothing - }), - errorHeader: jest.fn(() => undefined) - }, - progress: { - startBar: jest.fn((parms) => undefined), - endBar: jest.fn(() => undefined) - }, - format: { - output: jest.fn((parms) => { - // Nothing - }) - } - }, - definition: { - customize: { - profileTypeIdentifier: "fake" - } - }, - fullDefinition: undefined, - profiles: undefined -}; - -describe("list profiles handler", () => { - - // Reset mocks for counters, etc. - afterEach(() => { - jest.resetAllMocks(); - }); - - describe("error handling", () => { - it("should not transform errors from the profile manager", async () => { - // "Mock" with the object here - Object.defineProperty(Imperative, "api", { value: MockedImperativeAPIError, configurable: true }); - const handlerReq = require("../../../src/profiles/handlers/ListProfilesHandler"); - const handler = new handlerReq.default(); - const parms = Object.assign({}, ...[HANDLER_PARAMETERS]); - let error; - try { - await handler.process(parms); - } catch (err) { - error = err; - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - it("should catch profileIO errors", async () => { - let errorText: string = "not_yet_set"; - - // "Mocked" version of the handler parameters for a list profile command - const listProfileParms: any = { - arguments: { - $0: "zowe", - _: ["profiles", "list", "zosmf-profiles"], - }, - response: { - console: { - error: jest.fn((msgText) => { - errorText = msgText; - }) - } - }, - definition: { - customize: { - profileTypeIdentifier: "fakeType" - } - } - }; - - /* Pretend that we have a team config. - * config is a getter of a property, so mock we the property. - */ - Object.defineProperty(ImperativeConfig.instance, "config", { - configurable: true, - get: jest.fn(() => { - return { - exists: true - }; - }) - }); - - // pretend to crash when profileManager is created - const fakeProfileIoError = "Pretend a ProfileIO error occurred"; - Object.defineProperty(Imperative, "api", { - configurable: true, - value: { - profileManager: (args: any) => { - throw new Error(fakeProfileIoError); - } - } - }); - - const handlerReq = require("../../../src/profiles/handlers/ListProfilesHandler"); - const handler = new handlerReq.default(); - await handler.process(listProfileParms); - expect(errorText).toContain("An error occurred trying to list profiles"); - expect(errorText).toContain(fakeProfileIoError); - }); - }); - - describe("response", () => { - it("should load all profiles and display just the names", async () => { - // "Mock" with the object here - Object.defineProperty(Imperative, "api", { value: MockedImperativeAPI, configurable: true }); - const handlerReq = require("../../../src/profiles/handlers/ListProfilesHandler"); - const handler = new handlerReq.default(); - const parms = Object.assign({}, ...[HANDLER_PARAMETERS]); - parms.response.format.output = jest.fn((args) => { - expect(args).toMatchSnapshot(); - }); - parms.response.data.setObj = jest.fn((args) => { - expect(args).toMatchSnapshot(); - }); - parms.response.data.setMessage = jest.fn((args) => { - expect(args).toMatchSnapshot(); - }); - await handler.process(parms); - expect(parms.response.data.setMessage).toHaveBeenCalledTimes(1); - expect(parms.response.data.setObj).toHaveBeenCalledTimes(1); - }); - - it("should load all profiles and display all contents", async () => { - // "Mock" with the object here - Object.defineProperty(Imperative, "api", { value: MockedImperativeAPI, configurable: true }); - const handlerReq = require("../../../src/profiles/handlers/ListProfilesHandler"); - const handler = new handlerReq.default(); - const parms = Object.assign({}, ...[HANDLER_PARAMETERS]); - parms.arguments.showContents = true; - parms.response.format.output = jest.fn((args) => { - expect(args).toMatchSnapshot(); - }); - parms.response.data.setObj = jest.fn((args) => { - expect(args).toMatchSnapshot(); - }); - parms.response.data.setMessage = jest.fn((args) => { - expect(args).toMatchSnapshot(); - }); - await handler.process(parms); - expect(parms.response.data.setMessage).toHaveBeenCalledTimes(1); - expect(parms.response.data.setObj).toHaveBeenCalledTimes(1); - }); - }); -}); diff --git a/packages/imperative/src/imperative/__tests__/profiles/handlers/NewDeleteProfilesHandler.unit.test.ts b/packages/imperative/src/imperative/__tests__/profiles/handlers/NewDeleteProfilesHandler.unit.test.ts deleted file mode 100644 index 6801595838..0000000000 --- a/packages/imperative/src/imperative/__tests__/profiles/handlers/NewDeleteProfilesHandler.unit.test.ts +++ /dev/null @@ -1,178 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -jest.mock("../../../src/Imperative"); -jest.mock("../../../../utilities/src/ImperativeConfig"); - -import { IProfileLoaded } from "../../../../profiles"; -import { Imperative } from "../../../src/Imperative"; -import { ImperativeConfig } from "../../../../utilities"; - -const fakeProfileIoError = "Pretend a ProfileIO error occurred"; -const noMsgText = "No message text"; - -let errorText: string = noMsgText; -let logText: string = noMsgText; - -// "Mocked" version of the handler parameters for a delete profile command -const deleteProfileParms: any = { - arguments: { - $0: "zowe", - _: ["profiles", "delete", "zosmf-profile", "ProfileToDelete"], - }, - response: { - data: { - setMessage: jest.fn((setMsgArgs) => { - // Nothing - }), - setObj: jest.fn((setObjArgs) => { - // Nothing - }) - }, - console: { - log: jest.fn((msgText) => { - logText = msgText; - }), - error: jest.fn((msgText) => { - errorText = msgText; - }) - } - }, - definition: { - customize: { - profileTypeIdentifier: "fakeType" - } - } -}; - -// "Mocked" profiles -const FAKE_PROFS: IProfileLoaded[] = [ - { - message: "loaded", - type: "fake", - failNotFound: true, - name: "fake1", - profile: { - name: "fake1", - type: "fake", - data: "some data", - info: "some info", - nested: { - data: "nested data" - } - } - }, - { - message: "loaded", - type: "fake", - failNotFound: true, - name: "fake", - profile: { - name: "fake2", - type: "fake", - data: "some data", - info: "some info", - nested: { - data: "nested data" - } - } - } -]; - -const ProfileDeleted = { - overwritten: true, - path: "this/is/a/great/path", - profile: { - type: "fakeProfileType" - } -}; - -// "Mocked" version of a crashing imperative API -const impApiMockedCrash = { - profileManager: (args: any) => { - throw new Error(fakeProfileIoError); - }, -}; - -// "Mocked" version of a successful imperative API - done here rather than a manual mock -const impApiMockedOk = { - profileManager: (args: any) => { - return { - getDefaultProfileName: jest.fn(() => { - return "fake1"; - }), - loadAll: jest.fn((loadArgs) => { - return JSON.parse(JSON.stringify(FAKE_PROFS)); - }), - delete: jest.fn(() => { - return ProfileDeleted; - }), - }; - }, -}; - - -describe("delete profile handler", () => { - - // Reset mocks for counters, etc. - beforeEach(() => { - errorText = noMsgText; - logText = noMsgText; - }); - - describe("successful operation", () => { - it("should delete a profile", async () => { - /* Pretend that we have **no** team config. - * config is a getter of a property, so mock we the property. - */ - Object.defineProperty(ImperativeConfig.instance, "config", { - configurable: true, - get: jest.fn(() => { - return { - exists: false - }; - }) - }); - - Object.defineProperty(Imperative, "api", { value: impApiMockedOk, configurable: true }); - const parms = Object.assign({}, ...[deleteProfileParms]); - const handlerReq = require("../../../src/profiles/handlers/NewDeleteProfilesHandler"); - const handler = new handlerReq.default(); - - await handler.process(deleteProfileParms); - expect(errorText).toBe(noMsgText); - expect(logText).toContain("was successfully deleted"); - }); - }); - - describe("error handling", () => { - it("should catch profileIO errors", async () => { - /* Pretend that we have a team config. - * config is a getter of a property, so mock we the property. - */ - Object.defineProperty(ImperativeConfig.instance, "config", { - configurable: true, - get: jest.fn(() => { - return { - exists: true - }; - }) - }); - - Object.defineProperty(Imperative, "api", { value: impApiMockedCrash, configurable: true }); - const handlerReq = require("../../../src/profiles/handlers/NewDeleteProfilesHandler"); - const handler = new handlerReq.default(); - await handler.process(deleteProfileParms); - expect(errorText).toContain("An error occurred trying to delete a profile"); - expect(errorText).toContain(fakeProfileIoError); - }); - }); -}); diff --git a/packages/imperative/src/imperative/__tests__/profiles/handlers/UpdateProfilesHandler.unit.test.ts b/packages/imperative/src/imperative/__tests__/profiles/handlers/UpdateProfilesHandler.unit.test.ts deleted file mode 100644 index 0032535b69..0000000000 --- a/packages/imperative/src/imperative/__tests__/profiles/handlers/UpdateProfilesHandler.unit.test.ts +++ /dev/null @@ -1,178 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -jest.mock("../../../src/Imperative"); -jest.mock("../../../../utilities/src/ImperativeConfig"); - -import { IProfileLoaded } from "../../../../profiles"; -import { Imperative } from "../../../src/Imperative"; -import { ImperativeConfig } from "../../../../utilities"; - -const fakeProfileIoError = "Pretend a ProfileIO error occurred"; -const noMsgText = "No message text"; - -let errorText: string = noMsgText; -let logText: string = noMsgText; - -// "Mocked" version of the handler parameters for an update profile command -const updateProfileParms: any = { - arguments: { - $0: "zowe", - _: ["profiles", "update", "zosmf-profiles", "newProfName"], - }, - response: { - data: { - setMessage: jest.fn((setMsgArgs) => { - // Nothing - }), - setObj: jest.fn((setObjArgs) => { - // Nothing - }) - }, - console: { - log: jest.fn((msgText) => { - logText = msgText; - }), - error: jest.fn((msgText) => { - errorText = msgText; - }) - } - }, - definition: { - customize: { - profileTypeIdentifier: "fakeType" - } - } -}; - -// "Mocked" profiles -const FAKE_PROFS: IProfileLoaded[] = [ - { - message: "loaded", - type: "fake", - failNotFound: true, - name: "fake1", - profile: { - name: "fake1", - type: "fake", - data: "some data", - info: "some info", - nested: { - data: "nested data" - } - } - }, - { - message: "loaded", - type: "fake", - failNotFound: true, - name: "fake", - profile: { - name: "fake2", - type: "fake", - data: "some data", - info: "some info", - nested: { - data: "nested data" - } - } - } -]; - -const ProfileUpdated = { - overwritten: true, - path: "this/is/a/great/path", - profile: { - type: "fakeProfileType" - } -}; - -// "Mocked" version of a crashing imperative API -const impApiMockedCrash = { - profileManager: (args: any) => { - throw new Error(fakeProfileIoError); - }, -}; - -// "Mocked" version of a successful imperative API - done here rather than a manual mock -const impApiMockedOk = { - profileManager: (args: any) => { - return { - getDefaultProfileName: jest.fn(() => { - return "fake1"; - }), - loadAll: jest.fn((loadArgs) => { - return JSON.parse(JSON.stringify(FAKE_PROFS)); - }), - update: jest.fn(() => { - return ProfileUpdated; - }), - }; - }, -}; - - -describe("update profile handler", () => { - - // Reset mocks for counters, etc. - beforeEach(() => { - errorText = noMsgText; - logText = noMsgText; - }); - - describe("successful operation", () => { - it("should update a profile", async () => { - /* Pretend that we have **no** team config. - * config is a getter of a property, so mock we the property. - */ - Object.defineProperty(ImperativeConfig.instance, "config", { - configurable: true, - get: jest.fn(() => { - return { - exists: false - }; - }) - }); - - Object.defineProperty(Imperative, "api", { value: impApiMockedOk, configurable: true }); - const parms = Object.assign({}, ...[updateProfileParms]); - const handlerReq = require("../../../src/profiles/handlers/UpdateProfilesHandler"); - const handler = new handlerReq.default(); - - await handler.process(updateProfileParms); - expect(errorText).toBe(noMsgText); - expect(logText).toContain("Review the created profile"); - }); - }); - - describe("error handling", () => { - it("should catch profileIO errors", async () => { - /* Pretend that we have a team config. - * config is a getter of a property, so mock we the property. - */ - Object.defineProperty(ImperativeConfig.instance, "config", { - configurable: true, - get: jest.fn(() => { - return { - exists: true - }; - }) - }); - - Object.defineProperty(Imperative, "api", { value: impApiMockedCrash, configurable: true }); - const handlerReq = require("../../../src/profiles/handlers/UpdateProfilesHandler"); - const handler = new handlerReq.default(); - await handler.process(updateProfileParms); - expect(errorText).toContain("An error occurred trying to update a profile"); - expect(errorText).toContain(fakeProfileIoError); - }); - }); -}); diff --git a/packages/imperative/src/imperative/__tests__/profiles/handlers/ValidateProfileHandler.unit.test.ts b/packages/imperative/src/imperative/__tests__/profiles/handlers/ValidateProfileHandler.unit.test.ts deleted file mode 100644 index 406679f58c..0000000000 --- a/packages/imperative/src/imperative/__tests__/profiles/handlers/ValidateProfileHandler.unit.test.ts +++ /dev/null @@ -1,202 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -jest.mock("../../../src/Imperative"); -jest.mock("../../../../utilities/src/ImperativeConfig"); - -import { IProfileLoaded, ProfileValidator } from "../../../../profiles"; -import { ICommandProfileTypeConfiguration } from "../../../../cmd"; -import { Imperative } from "../../../src/Imperative"; -import { ImperativeConfig } from "../../../../utilities"; - -const fakeProfileIoError = "Pretend a ProfileIO error occurred"; -const noMsgText = "No message text"; - -let errorText: string = noMsgText; -let logText: string = noMsgText; - -// "Mocked" version of the handler parameters for a validate profile command -const validateProfileParms: any = { - arguments: { - $0: "zowe", - _: ["profiles", "validate", "endevor-profile", "endvProfName", "--print-plan-only"], - "print-plan-only": true - }, - response: { - data: { - setMessage: jest.fn((setMsgArgs) => { - // Nothing - }), - setObj: jest.fn((setObjArgs) => { - // Nothing - }) - }, - console: { - log: jest.fn((msgText) => { - logText = msgText; - }), - error: jest.fn((msgText) => { - errorText = msgText; - }) - } - }, - definition: { - customize: { - profileTypeIdentifier: "fakeType" - } - } -}; - -// "Mocked" profiles -const FAKE_PROFS: IProfileLoaded[] = [ - { - message: "loaded", - type: "fake", - failNotFound: true, - name: "fake1", - profile: { - name: "fake1", - type: "fake", - data: "some data", - info: "some info", - nested: { - data: "nested data" - } - } - }, - { - message: "loaded", - type: "fake", - failNotFound: true, - name: "fake", - profile: { - name: "fake2", - type: "fake", - data: "some data", - info: "some info", - nested: { - data: "nested data" - } - } - } -]; - -const ProfileLoaded = { - overwritten: true, - path: "this/is/a/great/path", - profile: { - type: "fakeProfileType" - } -}; - -// "Mocked" version of a crashing imperative API -const impApiMockedCrash = { - profileManager: (args: any) => { - throw new Error(fakeProfileIoError); - }, -}; - -// "Mocked" version of a successful imperative API - done here rather than a manual mock -const impApiMockedOk = { - profileManager: (args: any) => { - return { - getDefaultProfileName: jest.fn(() => { - return "fake1"; - }), - loadAll: jest.fn((loadArgs) => { - return JSON.parse(JSON.stringify(FAKE_PROFS)); - }), - load: jest.fn(() => { - return ProfileLoaded; - }), - }; - }, -}; - - -describe("validate endevor profile handler", () => { - - // Reset mocks for counters, etc. - beforeEach(() => { - errorText = noMsgText; - logText = noMsgText; - }); - - describe("successful operation", () => { - it("should validate a profile", async () => { - /* Pretend that we have **no** team config. - * config is a getter of a property, so mock we the property. - */ - Object.defineProperty(ImperativeConfig.instance, "config", { - configurable: true, - get: jest.fn(() => { - return { - exists: false - }; - }) - }); - - const profConfig: ICommandProfileTypeConfiguration = { - type: "endevor", - schema: { - type: "endevor", - title: "some title", - description: "some description", - properties: { - type: { - type: "boolean" - }, - } - }, - validationPlanModule: "../../../../../__tests__/src/packages/imperative/plugins/test_cli/TestProfileValidationPlan1" - }; - Imperative.getProfileConfiguration = jest.fn(() => profConfig); - - // print-plan-only forced printing the plan, not validating - const printedPlanText = "Printed plan for profile validation"; - ProfileValidator.getTextDisplayForPlan = jest.fn(() => { - return printedPlanText; - }); - - Object.defineProperty(Imperative, "api", { value: impApiMockedOk, configurable: true }); - const parms = Object.assign({}, ...[validateProfileParms]); - const handlerReq = require("../../../src/profiles/handlers/ValidateProfileHandler"); - const handler = new handlerReq.default(); - - await handler.process(validateProfileParms); - expect(errorText).toBe(noMsgText); - expect(logText.toString()).toContain(printedPlanText); - }); - }); - - describe("error handling", () => { - it("should catch profileIO errors", async () => { - /* Pretend that we have a team config. - * config is a getter of a property, so mock we the property. - */ - Object.defineProperty(ImperativeConfig.instance, "config", { - configurable: true, - get: jest.fn(() => { - return { - exists: true - }; - }) - }); - - Object.defineProperty(Imperative, "api", { value: impApiMockedCrash, configurable: true }); - const handlerReq = require("../../../src/profiles/handlers/ValidateProfileHandler"); - const handler = new handlerReq.default(); - await handler.process(validateProfileParms); - expect(errorText).toContain("An error occurred trying to validate a profile"); - expect(errorText).toContain(fakeProfileIoError); - }); - }); -}); diff --git a/packages/imperative/src/imperative/__tests__/profiles/handlers/__snapshots__/ListProfilesHandler.unit.test.ts.snap b/packages/imperative/src/imperative/__tests__/profiles/handlers/__snapshots__/ListProfilesHandler.unit.test.ts.snap deleted file mode 100644 index 3dccde326d..0000000000 --- a/packages/imperative/src/imperative/__tests__/profiles/handlers/__snapshots__/ListProfilesHandler.unit.test.ts.snap +++ /dev/null @@ -1,144 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`list profiles handler error handling should not transform errors from the profile manager 1`] = `"ERROR!"`; - -exports[`list profiles handler response should load all profiles and display all contents 1`] = `"\\"2\\" profiles loaded for type \\"fake\\""`; - -exports[`list profiles handler response should load all profiles and display all contents 2`] = ` -Array [ - Object { - "failNotFound": true, - "message": "loaded", - "name": "fake1", - "profile": Object { - "data": "some data", - "info": "some info", - "name": "fake1", - "nested": Object { - "data": "nested data", - }, - "type": "fake", - }, - "type": "fake", - }, - Object { - "failNotFound": true, - "message": "loaded", - "name": "fake", - "profile": Object { - "data": "some data", - "info": "some info", - "name": "fake2", - "nested": Object { - "data": "nested data", - }, - "type": "fake", - }, - "type": "fake", - }, -] -`; - -exports[`list profiles handler response should load all profiles and display all contents 3`] = ` -Object { - "format": "object", - "output": Array [ - Object { - "contents": Object { - "data": "some data", - "info": "some info", - "name": "fake1", - "nested": Object { - "data": "nested data", - }, - "type": "fake", - }, - "name": "fake1 (default) ", - }, - Object { - "contents": Object { - "data": "some data", - "info": "some info", - "name": "fake2", - "nested": Object { - "data": "nested data", - }, - "type": "fake", - }, - "name": "fake", - }, - ], -} -`; - -exports[`list profiles handler response should load all profiles and display just the names 1`] = `"\\"2\\" profiles loaded for type \\"fake\\""`; - -exports[`list profiles handler response should load all profiles and display just the names 2`] = ` -Array [ - Object { - "failNotFound": true, - "message": "loaded", - "name": "fake1", - "profile": Object { - "data": "some data", - "info": "some info", - "name": "fake1", - "nested": Object { - "data": "nested data", - }, - "type": "fake", - }, - "type": "fake", - }, - Object { - "failNotFound": true, - "message": "loaded", - "name": "fake", - "profile": Object { - "data": "some data", - "info": "some info", - "name": "fake2", - "nested": Object { - "data": "nested data", - }, - "type": "fake", - }, - "type": "fake", - }, -] -`; - -exports[`list profiles handler response should load all profiles and display just the names 3`] = ` -Object { - "fields": Array [ - "name", - ], - "format": "list", - "output": Array [ - Object { - "contents": Object { - "data": "some data", - "info": "some info", - "name": "fake1", - "nested": Object { - "data": "nested data", - }, - "type": "fake", - }, - "name": "fake1 (default) ", - }, - Object { - "contents": Object { - "data": "some data", - "info": "some info", - "name": "fake2", - "nested": Object { - "data": "nested data", - }, - "type": "fake", - }, - "name": "fake", - }, - ], -} -`; diff --git a/packages/imperative/src/imperative/index.ts b/packages/imperative/src/imperative/index.ts index f5b505beb9..e34d98c792 100644 --- a/packages/imperative/src/imperative/index.ts +++ b/packages/imperative/src/imperative/index.ts @@ -16,14 +16,15 @@ export * from "./src/doc/IImperativeEnvironmentalVariableSetting"; export * from "./src/doc/IImperativeEnvironmentalVariableSettings"; export * from "./src/doc/IImperativeConfig"; export * from "./src/doc/IImperativeLoggingConfig"; -export * from "./src/ConfigurationLoader"; -export * from "./src/ConfigurationValidator"; -export * from "./src/DefinitionTreeResolver"; +export * from "./src/doc/IImperativeVersions"; +// export * from "./src/ConfigurationLoader"; +// export * from "./src/ConfigurationValidator"; +// export * from "./src/DefinitionTreeResolver"; export * from "./src/Imperative"; export * from "./src/LoggingConfigurer"; export * from "./src/plugins/AbstractPluginLifeCycle"; export * from "./src/plugins/PluginManagementFacility"; export * from "./src/auth/doc/IAuthHandlerApi"; -export * from "./src/auth/handlers/AbstractAuthHandler"; +// export * from "./src/auth/handlers/AbstractAuthHandler"; export * from "./src/auth/handlers/BaseAuthHandler"; export * from "./src/config/cmd/auto-init/handlers/BaseAutoInitHandler"; diff --git a/packages/imperative/src/imperative/src/ConfigurationValidator.ts b/packages/imperative/src/imperative/src/ConfigurationValidator.ts index 701d748e96..eb956d68b3 100644 --- a/packages/imperative/src/imperative/src/ConfigurationValidator.ts +++ b/packages/imperative/src/imperative/src/ConfigurationValidator.ts @@ -80,16 +80,14 @@ export class ConfigurationValidator { const property: ICommandProfileProperty = profileConfig.schema.properties[propertyName]; if (!(property.optionDefinitions == null) && - property.optionDefinitions.length > 1 && - profileConfig.createProfileFromArgumentsHandler == null) { + property.optionDefinitions.length > 1) + { throw new ImperativeError({ msg: TextUtils.formatMessage( - "Your Imperative profile configuration of type \"{{type}}\"" + - " has the schema property \"{{property}}\", which has multiple " + - "option definitions, but no handler for creating a profile from " + - "command line arguments. Imperative will not be able to determine " + - "how to map multiple command line arguments to a single profile property " + - "unless you provide a custom handler.", + "Your Imperative profile configuration of type \"{{type}}\" " + + "has the schema property \"{{property}}\", which has multiple " + + "option definitions. Imperative is not be able to " + + "map multiple command line arguments to a single profile property.", { type: profileConfig.type, property: propertyName diff --git a/packages/imperative/src/imperative/src/DefinitionTreeResolver.ts b/packages/imperative/src/imperative/src/DefinitionTreeResolver.ts index 53d4f80322..19c2f4bd7f 100644 --- a/packages/imperative/src/imperative/src/DefinitionTreeResolver.ts +++ b/packages/imperative/src/imperative/src/DefinitionTreeResolver.ts @@ -127,8 +127,9 @@ export class DefinitionTreeResolver { } catch (e) { throw new ImperativeError({ msg: "Encountered an error loading one of the files (" - + match + ") that matched the provided " + - "command module glob for the glob " + childGlob + ": " + e.message + + match + ") that matched the provided " + + "command module glob for the glob " + childGlob + ": " + e.message, + causeErrors: e }); } @@ -149,7 +150,7 @@ export class DefinitionTreeResolver { private static addBaseProfile(cmdDefs: ICommandDefinition[]): ICommandDefinition[] { return cmdDefs.map((cmdDef: ICommandDefinition) => { if (cmdDef.profile && Object.keys(cmdDef.profile).length > 0) { - cmdDef.profile.optional = [...(cmdDef.profile.optional || []), "base"]; + cmdDef.profile.optional = [...cmdDef.profile.optional || [], "base"]; } if (cmdDef.children && cmdDef.children.length > 0) { cmdDef.children = this.addBaseProfile(cmdDef.children); diff --git a/packages/imperative/src/imperative/src/Imperative.ts b/packages/imperative/src/imperative/src/Imperative.ts index 673b43c142..76eab278a5 100644 --- a/packages/imperative/src/imperative/src/Imperative.ts +++ b/packages/imperative/src/imperative/src/Imperative.ts @@ -30,7 +30,6 @@ import { PluginManagementFacility } from "./plugins/PluginManagementFacility"; // import { ConfigManagementFacility } from "./config/ConfigManagementFacility"; import { AbstractCommandYargs } from "../../cmd/src/yargs/AbstractCommandYargs"; -import { CliProfileManager } from "../../cmd/src/profiles/CliProfileManager"; import { CommandPreparer } from "../../cmd/src/CommandPreparer"; import { CommandYargs } from "../../cmd/src/yargs/CommandYargs"; import { ICommandDefinition } from "../../cmd/src/doc/ICommandDefinition"; @@ -44,12 +43,9 @@ import { WebHelpManager } from "../../cmd/src/help/WebHelpManager"; import { YargsConfigurer } from "../../cmd/src/yargs/YargsConfigurer"; import { YargsDefiner } from "../../cmd/src/yargs/YargsDefiner"; -import { ProfileUtils } from "../../profiles/src/utils/ProfileUtils"; import { IProfileTypeConfiguration } from "../../profiles/src/doc/config/IProfileTypeConfiguration"; -import { CompleteProfilesGroupBuilder } from "./profiles/builders/CompleteProfilesGroupBuilder"; import { ImperativeHelpGeneratorFactory } from "./help/ImperativeHelpGeneratorFactory"; import { OverridesLoader } from "./OverridesLoader"; -import { ImperativeProfileManagerFactory } from "./profiles/ImperativeProfileManagerFactory"; import { DefinitionTreeResolver } from "./DefinitionTreeResolver"; import { EnvironmentalVariableSettings } from "./env/EnvironmentalVariableSettings"; import { AppSettings } from "../../settings/src/AppSettings"; @@ -133,8 +129,7 @@ export class Imperative { /** * Identify caller's location on the system */ - // eslint-disable-next-line deprecation/deprecation - ImperativeConfig.instance.callerLocation = process.mainModule.filename; + ImperativeConfig.instance.callerLocation = require.main.filename; /** * Load callers configuration, validate, and save @@ -279,14 +274,6 @@ export class Imperative { // final preparation of the command tree const preparedHostCliCmdTree = this.getPreparedCmdTree(resolvedHostCliCmdTree, config.baseProfile); - /** - * Only initialize the old-school profile environment - * if we are not in team-config mode. - */ - if (ImperativeConfig.instance.config.exists === false) { - await this.initProfiles(config); - } - /** * Define all known commands */ @@ -416,15 +403,6 @@ export class Imperative { return TextUtils.chalk[ImperativeConfig.instance.loadedConfig.primaryTextColor](text); } - /** - * Get the configured environmental variable prefix for the user's CLI - * @returns {string} - the configured or default prefix for environmental variables for use in the environmental variable service - * @deprecated Please use ImperativeConfig.instance.envVariablePrefix - */ - public static get envVariablePrefix(): string { - return ImperativeConfig.instance.envVariablePrefix; - } - /** * Highlight text with your configured (or default) secondary color * @param {string} text - the text to highlight @@ -527,25 +505,6 @@ export class Imperative { Logger.initLogger(loggingConfig); } - /** - * Initialize the profiles directory with types and meta files. This can be called every startup of the CLI - * without issue, but if the meta files or configuration changes, we'll have to re-initialize. - * TODO: Determine the re-initialize strategy. - * @private - * @static - * @param {IImperativeConfig} config - The configuration document passed to init. - * @memberof Imperative - */ - private static async initProfiles(config: IImperativeConfig) { - if (config.profiles != null && config.profiles.length > 0) { - await CliProfileManager.initialize({ - configuration: config.profiles, - profileRootDirectory: ProfileUtils.constructProfilesRootDirectory(ImperativeConfig.instance.cliHome), - reinitialize: false - }); - } - } - /** * Define to yargs for main CLI and plugins * @@ -565,7 +524,6 @@ export class Imperative { preparedHostCliCmdTree, yargs, commandResponseParms, - new ImperativeProfileManagerFactory(this.api), this.mHelpGeneratorFactory, ImperativeConfig.instance.loadedConfig.experimentalCommandDescription, Imperative.rootCommandName, @@ -585,7 +543,6 @@ export class Imperative { Imperative.rootCommandName, Imperative.commandLine, ImperativeConfig.instance.envVariablePrefix, - new ImperativeProfileManagerFactory(this.api), this.mHelpGeneratorFactory, ImperativeConfig.instance.loadedConfig.experimentalCommandDescription, @@ -720,7 +677,6 @@ export class Imperative { if (loadedConfig.baseProfile != null) { allProfiles.push(loadedConfig.baseProfile); } - rootCommand.children.push(CompleteProfilesGroupBuilder.getProfileGroup(allProfiles, this.log)); } const authConfigs: {[key: string]: ICommandProfileAuthConfig[]} = {}; if (loadedConfig.profiles != null) { diff --git a/packages/imperative/src/imperative/src/LoggingConfigurer.ts b/packages/imperative/src/imperative/src/LoggingConfigurer.ts index bdd526d22c..dfa47fb9a8 100644 --- a/packages/imperative/src/imperative/src/LoggingConfigurer.ts +++ b/packages/imperative/src/imperative/src/LoggingConfigurer.ts @@ -9,12 +9,12 @@ * */ +import * as path from "path"; import { IConfigLogging } from "../../logger/src/doc/IConfigLogging"; import { Logger } from "../../logger/src/Logger"; import { LoggerConfigBuilder } from "../../logger/src/LoggerConfigBuilder"; import { IImperativeConfig } from "./doc/IImperativeConfig"; import { Console } from "../../console"; -import { IO } from "../../io/src/IO"; import { IImperativeLoggingConfig } from "./doc/IImperativeLoggingConfig"; import { ImperativeError } from "../../error/src/ImperativeError"; import { ImperativeExpect } from "../../expect/src/ImperativeExpect"; @@ -88,7 +88,7 @@ export class LoggingConfigurer { /** * All remaining logs are created here */ - if (!(imperativeConfig.logging.additionalLogging == null)) { + if (imperativeConfig.logging.additionalLogging != null) { imperativeConfig.logging.additionalLogging.forEach((logConfig) => { if (logConfig.apiName == null) { throw new ImperativeError({ @@ -159,11 +159,9 @@ export class LoggingConfigurer { */ private static configureLoggerByKey( home: string, imperativeConfig: IImperativeConfig, loggingConfig: IConfigLogging, entryKey: string, configKey: string) { - if (!(imperativeConfig.logging == null)) { - if (!(imperativeConfig.logging[configKey] == null)) { - loggingConfig = LoggingConfigurer.configureLoggerByKeyHelper( - home, imperativeConfig.logging[configKey], loggingConfig, entryKey, configKey); - } + if (imperativeConfig.logging != null && imperativeConfig.logging[configKey] != null) { + loggingConfig = LoggingConfigurer.configureLoggerByKeyHelper( + home, imperativeConfig.logging[configKey], loggingConfig, entryKey, configKey); } return loggingConfig; @@ -183,12 +181,12 @@ export class LoggingConfigurer { */ private static configureLoggerByKeyHelper(home: string, impLogConfig: IImperativeLoggingConfig, loggingConfig: IConfigLogging, entryKey: string, configKey: string) { - if (!(impLogConfig.logFile == null)) { + if (impLogConfig.logFile != null) { const fullLogFilePath = home + LoggingConfigurer.normalizeDir(impLogConfig.logFile); loggingConfig.log4jsConfig.appenders[entryKey].filename = fullLogFilePath as any; } - if (!(impLogConfig.level == null)) { + if (impLogConfig.level != null) { Console.validateLevel(impLogConfig.level); loggingConfig.log4jsConfig.categories[entryKey].level = impLogConfig.level; } @@ -295,7 +293,7 @@ export class LoggingConfigurer { if (file[0] === "/" || file[0] === "\\") { return file; } else { - return IO.FILE_DELIM + file; + return path.posix.sep + file; } } } diff --git a/packages/imperative/src/imperative/src/OverridesLoader.ts b/packages/imperative/src/imperative/src/OverridesLoader.ts index 0cc865bed3..530dee32e4 100644 --- a/packages/imperative/src/imperative/src/OverridesLoader.ts +++ b/packages/imperative/src/imperative/src/OverridesLoader.ts @@ -65,25 +65,25 @@ export class OverridesLoader { const overrides: IImperativeOverrides = config.overrides; // The manager display name used to populate the "managed by" fields in profiles - const displayName: string = ( + const displayName: string = overrides.CredentialManager != null && AppSettings.initialized && AppSettings.instance.getNamespace("overrides") != null && AppSettings.instance.get("overrides", "CredentialManager") != null && AppSettings.instance.get("overrides", "CredentialManager") !== false - ) ? + ? // App settings is configured - use the plugin name for the manager name - AppSettings.instance.get("overrides", "CredentialManager") as string - : + AppSettings.instance.get("overrides", "CredentialManager") as string + : // App settings is not configured - use the CLI display name OR the package name as the manager name - config.productDisplayName || config.name; + config.productDisplayName || config.name; // Initialize the credential manager if an override was supplied and/or keytar was supplied in package.json if (overrides.CredentialManager != null || this.shouldUseKeytar(packageJson, useTeamConfig)) { let Manager = overrides.CredentialManager; if (typeof overrides.CredentialManager === "string" && !isAbsolute(overrides.CredentialManager)) { - // eslint-disable-next-line deprecation/deprecation - Manager = resolve(process.mainModule.filename, "../", overrides.CredentialManager); + const resolvePath = ImperativeConfig.instance.callerLocation ?? require.main.filename; + Manager = resolve(resolvePath, "../", overrides.CredentialManager); } await CredentialManagerFactory.initialize({ @@ -126,12 +126,12 @@ export class OverridesLoader { if (!CredentialManagerFactory.initialized) return; const vault: IConfigVault = { - load: ((key: string): Promise => { + load: (key: string): Promise => { return CredentialManagerFactory.manager.load(key, true); - }), - save: ((key: string, value: any): Promise => { + }, + save: (key: string, value: any): Promise => { return CredentialManagerFactory.manager.save(key, value); - }) + } }; try { diff --git a/packages/imperative/src/imperative/src/__mocks__/Imperative.ts b/packages/imperative/src/imperative/src/__mocks__/Imperative.ts index c35c52b03f..17cd5bc59e 100644 --- a/packages/imperative/src/imperative/src/__mocks__/Imperative.ts +++ b/packages/imperative/src/imperative/src/__mocks__/Imperative.ts @@ -10,7 +10,9 @@ */ import { TextUtils } from "../../../utilities/"; -import { AbstractHelpGenerator, DefaultHelpGenerator, IHelpGeneratorParms, ICommandDefinition } from "../../../cmd"; +import { AbstractHelpGenerator } from "../../../cmd/src/help/abstract/AbstractHelpGenerator"; +import { IHelpGeneratorParms } from "../../../cmd/src/help/doc/IHelpGeneratorParms"; +import { DefaultHelpGenerator, ICommandDefinition } from "../../../cmd"; import { IImperativeConfig } from "../doc/IImperativeConfig"; const PRIMARY_COLOR: string = "yellow"; diff --git a/packages/imperative/src/imperative/src/api/ImperativeApi.ts b/packages/imperative/src/imperative/src/api/ImperativeApi.ts index 5011223b6c..3fb75a82d9 100644 --- a/packages/imperative/src/imperative/src/api/ImperativeApi.ts +++ b/packages/imperative/src/imperative/src/api/ImperativeApi.ts @@ -12,8 +12,6 @@ import { IImperativeConfig } from "../doc/IImperativeConfig"; import { IImperativeApi } from "./doc/IImperativeApi"; import { Logger } from "../../../logger"; -import { ProfileUtils } from "../../../profiles"; -import { CliProfileManager } from "../../../cmd"; export class ImperativeApi { /** @@ -64,18 +62,4 @@ export class ImperativeApi { public addAdditionalLogger(name: string, logger: Logger): void { this.mCustomLoggerMap[name] = logger; } - - /** - * Return an instance of a profile manager for a given profile type - * See ProfileManager.ts for more details - */ - public profileManager(type: string): CliProfileManager { - return new CliProfileManager({ - type, - typeConfigurations: this.mConfig.profiles, - profileRootDirectory: ProfileUtils.constructProfilesRootDirectory(this.mHome), - logger: this.imperativeLogger, - productDisplayName: this.mConfig.productDisplayName - }); - } } diff --git a/packages/imperative/src/imperative/src/auth/__tests__/BaseAuthHandler.config.unit.test.ts b/packages/imperative/src/imperative/src/auth/__tests__/BaseAuthHandler.config.unit.test.ts index e4ebcf3690..12b0696866 100644 --- a/packages/imperative/src/imperative/src/auth/__tests__/BaseAuthHandler.config.unit.test.ts +++ b/packages/imperative/src/imperative/src/auth/__tests__/BaseAuthHandler.config.unit.test.ts @@ -10,6 +10,7 @@ */ jest.mock("../../../../logger/src/LoggerUtils"); + import * as fs from "fs"; import * as path from "path"; import * as lodash from "lodash"; @@ -20,7 +21,7 @@ import { Config } from "../../../../config"; import { IConfigSecure } from "../../../../config/src/doc/IConfigSecure"; import FakeAuthHandler from "./__data__/FakeAuthHandler"; import { CredentialManagerFactory } from "../../../../security"; -import { ImperativeError } from "../../../.."; +import { EventOperator, EventUtils, ImperativeError } from "../../../.."; const MY_APP = "my_app"; @@ -45,6 +46,11 @@ describe("BaseAuthHandler config", () => { }); }); + beforeEach(() => { + jest.spyOn(EventUtils, "validateAppName").mockImplementation(jest.fn()); + jest.spyOn(EventOperator, "getZoweProcessor").mockReturnValue({emitZoweEvent: jest.fn()} as any); + }); + afterEach(() => { jest.restoreAllMocks(); jest.clearAllMocks(); @@ -99,9 +105,9 @@ describe("BaseAuthHandler config", () => { } expect(caughtError).toBeUndefined(); - expect(doLoginSpy).toBeCalledTimes(1); + expect(doLoginSpy).toHaveBeenCalledTimes(1); expect(writeFileSpy).not.toHaveBeenCalled(); - expect(mockSetObj).toBeCalledTimes(1); + expect(mockSetObj).toHaveBeenCalledTimes(1); expect(mockSetObj.mock.calls[0][0]).toEqual({ tokenType: handler.mDefaultTokenType, tokenValue: "fakeToken" }); }); @@ -120,10 +126,10 @@ describe("BaseAuthHandler config", () => { } expect(caughtError).toBeUndefined(); - expect(doLoginSpy).toBeCalledTimes(1); - expect(params.response.console.prompt).toBeCalledTimes(1); + expect(doLoginSpy).toHaveBeenCalledTimes(1); + expect(params.response.console.prompt).toHaveBeenCalledTimes(1); expect(writeFileSpy).not.toHaveBeenCalled(); - expect(mockSetObj).toBeCalledTimes(1); + expect(mockSetObj).toHaveBeenCalledTimes(1); expect(mockSetObj.mock.calls[0][0]).toEqual({ tokenType: handler.mDefaultTokenType, tokenValue: "fakeToken" }); }); @@ -143,10 +149,10 @@ describe("BaseAuthHandler config", () => { } expect(caughtError).toBeUndefined(); - expect(doLoginSpy).toBeCalledTimes(1); - expect(params.response.console.prompt).toBeCalledTimes(1); + expect(doLoginSpy).toHaveBeenCalledTimes(1); + expect(params.response.console.prompt).toHaveBeenCalledTimes(1); expect(writeFileSpy).not.toHaveBeenCalled(); - expect(mockSetObj).toBeCalledTimes(1); + expect(mockSetObj).toHaveBeenCalledTimes(1); expect(mockSetObj.mock.calls[0][0]).toEqual({ tokenType: handler.mDefaultTokenType, tokenValue: "fakeToken" }); }); @@ -170,7 +176,7 @@ describe("BaseAuthHandler config", () => { expect(caughtError.message).toBe("Unable to securely save credentials."); expect(caughtError).toBeInstanceOf(ImperativeError); expect(caughtError.additionalDetails).toContain("FAKE_OPT_TOKEN_VALUE"); - expect(doLoginSpy).toBeCalledTimes(1); + expect(doLoginSpy).toHaveBeenCalledTimes(1); expect(writeFileSpy).not.toHaveBeenCalled(); }); @@ -191,10 +197,10 @@ describe("BaseAuthHandler config", () => { } expect(caughtError).toBeUndefined(); - expect(doLoginSpy).toBeCalledTimes(1); - expect(params.response.console.prompt).toBeCalledTimes(1); - expect(writeFileSpy).toBeCalledTimes(1); - expect(fakeVault.save).toBeCalledTimes(1); + expect(doLoginSpy).toHaveBeenCalledTimes(1); + expect(params.response.console.prompt).toHaveBeenCalledTimes(1); + expect(writeFileSpy).toHaveBeenCalledTimes(1); + expect(fakeVault.save).toHaveBeenCalledTimes(1); expect(fakeVault.save.mock.calls[0][1]).toContain(`"profiles.fruit_creds.properties.tokenValue":"fakeToken"`); expect(fakeConfig.properties.profiles.fruit_creds.properties).toEqual({ @@ -229,10 +235,10 @@ describe("BaseAuthHandler config", () => { } expect(caughtError).toBeUndefined(); - expect(doLoginSpy).toBeCalledTimes(1); - expect(params.response.console.prompt).toBeCalledTimes(1); - expect(writeFileSpy).toBeCalledTimes(1); - expect(fakeVault.save).toBeCalledTimes(1); + expect(doLoginSpy).toHaveBeenCalledTimes(1); + expect(params.response.console.prompt).toHaveBeenCalledTimes(1); + expect(writeFileSpy).toHaveBeenCalledTimes(1); + expect(fakeVault.save).toHaveBeenCalledTimes(1); expect(fakeVault.save.mock.calls[0][1]).toContain(`"profiles.fruit_creds.properties.tokenValue":"fakeToken"`); expect(fakeConfig.properties.profiles.fruit_creds.properties).toEqual({ @@ -266,9 +272,9 @@ describe("BaseAuthHandler config", () => { } expect(caughtError).toBeUndefined(); - expect(doLoginSpy).toBeCalledTimes(1); - expect(writeFileSpy).toBeCalledTimes(1); - expect(fakeVault.save).toBeCalledTimes(1); + expect(doLoginSpy).toHaveBeenCalledTimes(1); + expect(writeFileSpy).toHaveBeenCalledTimes(1); + expect(fakeVault.save).toHaveBeenCalledTimes(1); expect(fakeConfig.properties.profiles.fruit_creds).toBeUndefined(); expect(fakeVault.save.mock.calls[0][1]).toContain(`"profiles.fruit.properties.tokenValue":"fakeToken"`); @@ -313,9 +319,9 @@ describe("BaseAuthHandler config", () => { } expect(caughtError).toBeUndefined(); - expect(doLoginSpy).toBeCalledTimes(1); - expect(writeFileSpy).toBeCalledTimes(1); - expect(fakeVault.save).toBeCalledTimes(1); + expect(doLoginSpy).toHaveBeenCalledTimes(1); + expect(writeFileSpy).toHaveBeenCalledTimes(1); + expect(fakeVault.save).toHaveBeenCalledTimes(1); expect(fakeConfig.properties.profiles.fruit_creds).toBeUndefined(); expect(fakeVault.save.mock.calls[0][1]).toContain(`"profiles.fruit.properties.tokenValue":"fakeToken"`); @@ -361,9 +367,9 @@ describe("BaseAuthHandler config", () => { } expect(caughtError).toBeUndefined(); - expect(doLoginSpy).toBeCalledTimes(1); - expect(writeFileSpy).toBeCalledTimes(1); - expect(fakeVault.save).toBeCalledTimes(1); + expect(doLoginSpy).toHaveBeenCalledTimes(1); + expect(writeFileSpy).toHaveBeenCalledTimes(1); + expect(fakeVault.save).toHaveBeenCalledTimes(1); expect(fakeConfig.properties.profiles.fruit_creds).toBeUndefined(); expect(fakeVault.save.mock.calls[0][1]).toContain(`"profiles.fruit.properties.tokenValue":"fakeToken"`); @@ -409,9 +415,9 @@ describe("BaseAuthHandler config", () => { } expect(caughtError).toBeUndefined(); - expect(doLoginSpy).toBeCalledTimes(1); - expect(writeFileSpy).toBeCalledTimes(1); - expect(fakeVault.save).toBeCalledTimes(1); + expect(doLoginSpy).toHaveBeenCalledTimes(1); + expect(writeFileSpy).toHaveBeenCalledTimes(1); + expect(fakeVault.save).toHaveBeenCalledTimes(1); expect(fakeConfig.properties.profiles.fruit_creds).toBeUndefined(); expect(fakeVault.save.mock.calls[0][1]).toContain(`"profiles.fruit.properties.tokenValue":"fakeToken"`); @@ -463,6 +469,9 @@ describe("BaseAuthHandler config", () => { jest.spyOn(Config, "search").mockReturnValue(configPath); jest.spyOn(fs, "existsSync").mockReturnValueOnce(false).mockReturnValueOnce(true).mockReturnValue(false); fakeConfig = await Config.load(MY_APP, { vault: fakeVault }); + + jest.spyOn(EventUtils, "validateAppName").mockImplementation(jest.fn()); + jest.spyOn(EventOperator, "getZoweProcessor").mockReturnValue({emitZoweEvent: jest.fn()} as any); }); it("should logout successfully from profile specified by user", async () => { @@ -484,9 +493,9 @@ describe("BaseAuthHandler config", () => { } expect(caughtError).toBeUndefined(); - expect(doLogoutSpy).toBeCalledTimes(1); - expect(writeFileSpy).toBeCalledTimes(1); - expect(fakeVault.save).toBeCalledTimes(1); + expect(doLogoutSpy).toHaveBeenCalledTimes(1); + expect(writeFileSpy).toHaveBeenCalledTimes(1); + expect(fakeVault.save).toHaveBeenCalledTimes(1); expect(fakeVault.save.mock.calls[0][1]).toBe("{}"); expect(fakeConfig.properties.profiles.fruit.properties.tokenType).toBeUndefined(); expect(fakeConfig.properties.profiles.fruit.properties.tokenValue).toBeUndefined(); @@ -510,9 +519,9 @@ describe("BaseAuthHandler config", () => { } expect(caughtError).toBeUndefined(); - expect(doLogoutSpy).toBeCalledTimes(1); - expect(writeFileSpy).toBeCalledTimes(1); - expect(fakeVault.save).toBeCalledTimes(1); + expect(doLogoutSpy).toHaveBeenCalledTimes(1); + expect(writeFileSpy).toHaveBeenCalledTimes(1); + expect(fakeVault.save).toHaveBeenCalledTimes(1); expect(fakeVault.save.mock.calls[0][1]).toBe("{}"); expect(fakeConfig.properties.profiles.fruit.properties.tokenType).toBeUndefined(); expect(fakeConfig.properties.profiles.fruit.properties.tokenValue).toBeUndefined(); @@ -537,8 +546,8 @@ describe("BaseAuthHandler config", () => { } expect(caughtError).toBeUndefined(); - expect(doLogoutSpy).toBeCalledTimes(1); - expect(writeFileSpy).toBeCalledTimes(0); + expect(doLogoutSpy).toHaveBeenCalledTimes(1); + expect(writeFileSpy).toHaveBeenCalledTimes(0); expect(fakeConfig.properties.profiles.fruit.properties.tokenType).toBeDefined(); expect(fakeConfig.properties.profiles.fruit.properties.tokenValue).toBeDefined(); }); @@ -558,7 +567,7 @@ describe("BaseAuthHandler config", () => { } expect(caughtError).toBeUndefined(); - expect(doLogoutSpy).toBeCalledTimes(1); + expect(doLogoutSpy).toHaveBeenCalledTimes(1); expect(writeFileSpy).not.toHaveBeenCalled(); }); diff --git a/packages/imperative/src/imperative/src/auth/__tests__/BaseAuthHandler.unit.test.ts b/packages/imperative/src/imperative/src/auth/__tests__/BaseAuthHandler.unit.test.ts index e05e1e899f..22f4c344b2 100644 --- a/packages/imperative/src/imperative/src/auth/__tests__/BaseAuthHandler.unit.test.ts +++ b/packages/imperative/src/imperative/src/auth/__tests__/BaseAuthHandler.unit.test.ts @@ -10,26 +10,77 @@ */ import { IHandlerParameters } from "../../../../cmd"; -import { Imperative } from "../../Imperative"; +import { ConnectionPropsForSessCfg } from "../../../.."; import { ImperativeConfig } from "../../../.."; import FakeAuthHandler from "./__data__/FakeAuthHandler"; describe("BaseAuthHandler", () => { - const mockSaveProfile = jest.fn(); - const mockUpdateProfile = jest.fn(); + const configSaveMock = jest.fn(); + let teamCfgExistsMock = jest.fn(() => true); + let profileExistsMock = jest.fn(() => true); beforeAll(() => { - Object.defineProperty(Imperative, "api", { - get: () => ({ - profileManager: (profType: string) => ({ - save: mockSaveProfile, - update: mockUpdateProfile - }) - }) - }); + // we do not want to call the real addPropsOrPrompt + ConnectionPropsForSessCfg.addPropsOrPrompt = jest.fn((): any => ({ + hostname: "connHostNm", + port: 5678, + user: "connUser", + password: "connPassword" + })); + + // we do not want to use the real ImperativeConfig Object.defineProperty(ImperativeConfig, "instance", { get: () => ({ - config: { exists: false } + cliHome: (): string => "/fake/cli/home/path", + envVariablePrefix: (): string => "FAKE_ZOWE_CLI_PREFIX", + config: { + exists: teamCfgExistsMock, + set: (): any => null, + save: configSaveMock, + properties: { + defaults: { "zosmf": "fakeProfNm" }, + profiles: { + fakeProfNm: { + type: "zosmf", + host: "fakeHostNm", + port: 1234 + } + } + }, + api: { + secure: { + loadFailed: false, + securePropsForProfile: (): any => [] + }, + profiles: { + get: () => ({ + fakeProfNm: { + type: "zosmf", + host: "fakeHostNm", + port: 1234 + } + }), + set: jest.fn(), + defaultSet: jest.fn(), + exists: profileExistsMock, + getProfilePathFromName: () => "fake/path" + }, + layers: { + get: () => ({ + path: "fake/path", + exists: true, + properties: {}, + global: true, + user: false + }), + find: () => ({ + user: false, + global: true + }), + activate: (): any => null + } + } + } }) }); }); @@ -51,13 +102,13 @@ describe("BaseAuthHandler", () => { password: "fakePass" }, positionals: ["auth", "login"], - profiles: { - getMeta: jest.fn(() => ({ - name: "fakeName" - })) - } + profiles: {} } as any; + // report that we have a team config and a profile + teamCfgExistsMock = jest.fn(() => true); + profileExistsMock = jest.fn(() => true); + const doLoginSpy = jest.spyOn(handler as any, "doLogin"); let caughtError; @@ -68,8 +119,8 @@ describe("BaseAuthHandler", () => { } expect(caughtError).toBeUndefined(); - expect(doLoginSpy).toBeCalledTimes(1); - expect(mockUpdateProfile).toBeCalledTimes(1); + expect(doLoginSpy).toHaveBeenCalledTimes(1); + expect(configSaveMock).toHaveBeenCalledTimes(1); }); it("should process login successfully and create profile", async () => { @@ -85,12 +136,16 @@ describe("BaseAuthHandler", () => { user: "fakeUser", password: "fakePass" }, - positionals: ["auth", "login"], - profiles: { - getMeta: jest.fn() - } + positionals: ["auth", "login"] } as any; + // report user and password are in our secure properties + ImperativeConfig.instance.config.api.secure.securePropsForProfile = (): any => ["user", "password"]; + + // report that we have no team config and no profile + teamCfgExistsMock = jest.fn(() => false); + profileExistsMock = jest.fn(() => false); + const doLoginSpy = jest.spyOn(handler as any, "doLogin"); let caughtError; @@ -101,9 +156,9 @@ describe("BaseAuthHandler", () => { } expect(caughtError).toBeUndefined(); - expect(doLoginSpy).toBeCalledTimes(1); + expect(doLoginSpy).toHaveBeenCalledTimes(1); expect(params.response.console.prompt).toHaveBeenCalledTimes(1); - expect(mockSaveProfile).toBeCalledTimes(1); + expect(configSaveMock).toHaveBeenCalledTimes(1); }); it("should process login successfully without creating profile on timeout", async () => { @@ -122,12 +177,13 @@ describe("BaseAuthHandler", () => { user: "fakeUser", password: "fakePass" }, - positionals: ["auth", "login"], - profiles: { - getMeta: jest.fn() - } + positionals: ["auth", "login"] } as any; + // report that we have no team config and no profile + teamCfgExistsMock = jest.fn(() => false); + profileExistsMock = jest.fn(() => false); + const doLoginSpy = jest.spyOn(handler as any, "doLogin"); let caughtError; @@ -138,9 +194,9 @@ describe("BaseAuthHandler", () => { } expect(caughtError).toBeUndefined(); - expect(doLoginSpy).toBeCalledTimes(1); + expect(doLoginSpy).toHaveBeenCalledTimes(1); expect(params.response.console.prompt).toHaveBeenCalledTimes(1); - expect(mockSaveProfile).toBeCalledTimes(0); + expect(configSaveMock).toHaveBeenCalledTimes(0); }); it("should process logout successfully", async () => { @@ -160,19 +216,14 @@ describe("BaseAuthHandler", () => { user: "fakeUser", password: "fakePass" }, - positionals: ["auth", "logout"], - profiles: { - getMeta: jest.fn(() => ({ - name: "fakeName", - profile: { - tokenValue: "fakeToken" - } - })) - } + positionals: ["auth", "logout"] } as any; + // report that we have a team config and a profile + teamCfgExistsMock = jest.fn(() => true); + profileExistsMock = jest.fn(() => true); + const doLogoutSpy = jest.spyOn(handler as any, "doLogout"); - const processLogoutOldSpy = jest.spyOn(handler as any, "processLogoutOld"); let caughtError; try { @@ -182,19 +233,33 @@ describe("BaseAuthHandler", () => { } expect(caughtError).toBeUndefined(); - expect(doLogoutSpy).toBeCalledTimes(1); - expect(processLogoutOldSpy).toBeCalledTimes(1); + expect(doLogoutSpy).toHaveBeenCalledTimes(1); expect(params.arguments.tokenType).toEqual(handler.mDefaultTokenType); expect(params.arguments.user).toBeUndefined(); expect(params.arguments.password).toBeUndefined(); + expect(configSaveMock).toHaveBeenCalledTimes(0); + }); - it("should process logout successfully even when tokenValue is not provided", async () => { + it("should not logout when tokenValue is not provided", async () => { + let errMsg: string = ""; + let exitCode: number = 0; const handler = new FakeAuthHandler(); const params: IHandlerParameters = { response: { console: { - log: jest.fn() + log: jest.fn(), + errorHeader: jest.fn((_errMsg) => { + errMsg += _errMsg + "\n"; + }), + error: jest.fn((_errMsg) => { + errMsg += _errMsg + "\n"; + }), + }, + data: { + setExitCode: jest.fn((_exitCode) => { + exitCode = _exitCode; + }) } }, arguments: { @@ -203,16 +268,14 @@ describe("BaseAuthHandler", () => { tokenType: handler.mDefaultTokenType, tokenValue: null, }, - positionals: ["auth", "logout"], - profiles: { - getMeta: jest.fn(() => ({ - name: "fakeName" - })) - } + positionals: ["auth", "logout"] } as any; + // report that we have a team config and a profile + teamCfgExistsMock = jest.fn(() => true); + profileExistsMock = jest.fn(() => true); + const doLogoutSpy = jest.spyOn(handler as any, "doLogout"); - const processLogoutOldSpy = jest.spyOn(handler as any, "processLogoutOld"); let caughtError; try { @@ -222,8 +285,10 @@ describe("BaseAuthHandler", () => { } expect(caughtError).toBeUndefined(); - expect(doLogoutSpy).toBeCalledTimes(0); - expect(processLogoutOldSpy).toBeCalledTimes(1); + expect(doLogoutSpy).toHaveBeenCalledTimes(0); + expect(errMsg).toContain("Token was not provided, so can't log out"); + expect(errMsg).toContain("You need to authenticate first using `zowe auth login`"); + expect(exitCode).toEqual(1); }); it("should fail to process invalid action name", async () => { @@ -235,12 +300,7 @@ describe("BaseAuthHandler", () => { } }, arguments: {}, - positionals: ["auth", "invalid"], - profiles: { - getMeta: jest.fn(() => ({ - name: "fakeName" - })) - } + positionals: ["auth", "invalid"] } as any; let caughtError; @@ -268,12 +328,7 @@ describe("BaseAuthHandler", () => { user: "fakeUser", password: "fakePass" }, - positionals: ["auth", "login"], - profiles: { - getMeta: jest.fn(() => ({ - name: "fakeName" - })) - } + positionals: ["auth", "login"] } as any; const doLoginSpy = jest.spyOn(handler as any, "doLogin").mockResolvedValue(null); @@ -287,6 +342,6 @@ describe("BaseAuthHandler", () => { expect(caughtError).toBeDefined(); expect(caughtError.message).toContain("token value"); - expect(doLoginSpy).toBeCalledTimes(1); + expect(doLoginSpy).toHaveBeenCalledTimes(1); }); }); diff --git a/packages/imperative/src/imperative/src/auth/__tests__/__snapshots__/CompleteAuthGroupBuilder.unit.test.ts.snap b/packages/imperative/src/imperative/src/auth/__tests__/__snapshots__/CompleteAuthGroupBuilder.unit.test.ts.snap index f82029bf98..1e5ec2e7e8 100644 --- a/packages/imperative/src/imperative/src/auth/__tests__/__snapshots__/CompleteAuthGroupBuilder.unit.test.ts.snap +++ b/packages/imperative/src/imperative/src/auth/__tests__/__snapshots__/CompleteAuthGroupBuilder.unit.test.ts.snap @@ -39,7 +39,7 @@ Object { "base", ], }, - "summary": "Log in to fakeService authentication service", + "summary": "Log in to fakeService authentication service.", "type": "command", }, Object { @@ -73,7 +73,7 @@ Object { "base", ], }, - "summary": "Log in to fakeService authentication service", + "summary": "Log in to fakeService authentication service.", "type": "command", }, ], @@ -110,7 +110,7 @@ Object { "base", ], }, - "summary": "Log out of fakeService authentication service", + "summary": "Log out of fakeService authentication service.", "type": "command", }, Object { @@ -136,7 +136,7 @@ Object { "base", ], }, - "summary": "Log out of fakeService authentication service", + "summary": "Log out of fakeService authentication service.", "type": "command", }, ], @@ -181,7 +181,7 @@ Object { "base", ], }, - "summary": "Log in to fakeService authentication service", + "summary": "Log in to fakeService authentication service.", "type": "command", }, Object { @@ -215,7 +215,7 @@ Object { "base", ], }, - "summary": "Log in to fakeService authentication service", + "summary": "Log in to fakeService authentication service.", "type": "command", }, ], @@ -252,7 +252,7 @@ Object { "base", ], }, - "summary": "Log out of fakeService authentication service", + "summary": "Log out of fakeService authentication service.", "type": "command", }, Object { @@ -278,7 +278,7 @@ Object { "base", ], }, - "summary": "Log out of fakeService authentication service", + "summary": "Log out of fakeService authentication service.", "type": "command", }, ], @@ -288,7 +288,7 @@ Object { "type": "group", }, ], - "description": "Connect to token-based authentication services", + "description": "Connect to token-based authentication services.", "name": "auth", "summary": "Fake auth group summary", "type": "group", @@ -334,7 +334,7 @@ Object { "base", ], }, - "summary": "Log in to fakeService authentication service", + "summary": "Log in to fakeService authentication service.", "type": "command", }, ], @@ -371,7 +371,7 @@ Object { "base", ], }, - "summary": "Log out of fakeService authentication service", + "summary": "Log out of fakeService authentication service.", "type": "command", }, ], @@ -381,8 +381,9 @@ Object { "type": "group", }, ], - "description": "Connect to token-based authentication services", + "description": "Connect to token-based authentication services.", "name": "auth", + "summary": "Connect to token-based authentication services", "type": "group", } `; diff --git a/packages/imperative/src/imperative/src/auth/builders/AuthLoginCommandBuilder.ts b/packages/imperative/src/imperative/src/auth/builders/AuthLoginCommandBuilder.ts index 169722f28f..59f6f9e4c9 100644 --- a/packages/imperative/src/imperative/src/auth/builders/AuthLoginCommandBuilder.ts +++ b/packages/imperative/src/imperative/src/auth/builders/AuthLoginCommandBuilder.ts @@ -54,7 +54,7 @@ export class AuthLoginCommandBuilder extends AuthCommandBuilder { description: authLoginShowTokenDesc.message, type: "boolean" }, - ...(this.mConfig.login?.options || []) + ...this.mConfig.login?.options || [] ], examples: this.mConfig.login?.examples, profile: { diff --git a/packages/imperative/src/imperative/src/auth/builders/CompleteAuthGroupBuilder.ts b/packages/imperative/src/imperative/src/auth/builders/CompleteAuthGroupBuilder.ts index 0decbfc9a7..ddc1fe40e8 100644 --- a/packages/imperative/src/imperative/src/auth/builders/CompleteAuthGroupBuilder.ts +++ b/packages/imperative/src/imperative/src/auth/builders/CompleteAuthGroupBuilder.ts @@ -11,7 +11,7 @@ import { ICommandDefinition } from "../../../../cmd"; import { - authCategoryDesc, + authCategoryDesc, authCategorySummary, authLoginGroupDesc, authLoginGroupSummary, authLogoutGroupDesc, authLogoutGroupSummary } from "../../../../messages"; @@ -55,6 +55,7 @@ export class CompleteAuthGroupBuilder { private static defaultAuthGroup: ICommandDefinition = { name: Constants.AUTH_GROUP, + summary: authCategorySummary.message, description: authCategoryDesc.message, type: "group", children: [] diff --git a/packages/imperative/src/imperative/src/auth/handlers/AbstractAuthHandler.ts b/packages/imperative/src/imperative/src/auth/handlers/AbstractAuthHandler.ts index 9192694a52..5aceeff341 100644 --- a/packages/imperative/src/imperative/src/auth/handlers/AbstractAuthHandler.ts +++ b/packages/imperative/src/imperative/src/auth/handlers/AbstractAuthHandler.ts @@ -11,7 +11,7 @@ import { ICommandHandler, IHandlerParameters, ICommandArguments } from "../../../../cmd"; import { Constants } from "../../../../constants"; -import { AbstractSession, IOptionsForAddConnProps, ISession, SessConstants } from "../../../../rest"; +import { ISession, SessConstants } from "../../../../rest"; import { ImperativeError } from "../../../../error"; import { IAuthHandlerApi } from "../doc/IAuthHandlerApi"; @@ -60,17 +60,6 @@ export abstract class AbstractAuthHandler implements ICommandHandler { } } - /** - * This is called by the "config secure" handler when it needs to prompt - * for connection info to obtain an auth token. - * @deprecated Use `getAuthHandlerApi` instead - * @returns A tuple containing: - * - Options for adding connection properties - * - The login handler - */ - // eslint-disable-next-line deprecation/deprecation - public abstract getPromptParams(): [IOptionsForAddConnProps, (session: AbstractSession) => Promise]; - /** * Returns auth handler API that provides convenient functions to create a * session from args, and use it to login or logout of an auth service. diff --git a/packages/imperative/src/imperative/src/auth/handlers/BaseAuthHandler.ts b/packages/imperative/src/imperative/src/auth/handlers/BaseAuthHandler.ts index d7115b4ad2..0937d37e75 100644 --- a/packages/imperative/src/imperative/src/auth/handlers/BaseAuthHandler.ts +++ b/packages/imperative/src/imperative/src/auth/handlers/BaseAuthHandler.ts @@ -13,15 +13,11 @@ import { IHandlerParameters, IHandlerResponseApi } from "../../../../cmd"; import { AbstractSession, ConnectionPropsForSessCfg, - IOptionsForAddConnProps, ISession, RestConstants, - SessConstants, Session } from "../../../../rest"; -import { Imperative } from "../../Imperative"; import { IImperativeError, ImperativeError } from "../../../../error"; -import { ISaveProfileFromCliArgs } from "../../../../profiles"; import { ImperativeConfig } from "../../../../utilities"; import { ConfigUtils } from "../../../../config/src/ConfigUtils"; import { AbstractAuthHandler } from "./AbstractAuthHandler"; @@ -53,21 +49,6 @@ export abstract class BaseAuthHandler extends AbstractAuthHandler { */ protected abstract doLogout(session: AbstractSession): Promise; - /** - * This is called by the "config secure" handler when it needs to prompt - * for connection info to obtain an auth token. - * @deprecated Use `getAuthHandlerApi` instead - * @returns A tuple containing: - * - Options for adding connection properties - * - The login handler - */ - public getPromptParams(): [IOptionsForAddConnProps, (session: AbstractSession) => Promise] { - return [{ - defaultTokenType: this.mDefaultTokenType, - serviceDescription: this.mServiceDescription - }, this.doLogin]; - } - /** * Returns auth handler API that provides convenient functions to create a * session from args, and use it to login or logout of an auth service. @@ -114,9 +95,6 @@ export abstract class BaseAuthHandler extends AbstractAuthHandler { if (params.arguments.showToken) { // show token instead of updating profile this.showToken(params.response, tokenValue); - } else if (!ImperativeConfig.instance.config.exists) { - // process login for old school profiles - await this.processLoginOld(params, tokenValue); } else if (ImperativeConfig.instance.config.api.secure.loadFailed) { throw ConfigUtils.secureSaveError(`Instead of secure storage, ` + `rerun this command with the "--show-token" flag to print the token to console. ` + @@ -186,7 +164,7 @@ export abstract class BaseAuthHandler extends AbstractAuthHandler { `Do you want to store the host, port, and token on disk for use with future commands? If you answer Yes, the credentials will ` + `be saved to a ${this.mProfileType} profile named '${profileName}'. If you answer No, the token will be printed to the ` + `terminal and will not be stored on disk. [y/N]: `); - return (answer != null && (answer.toLowerCase() === "y" || answer.toLowerCase() === "yes")); + return answer != null && (answer.toLowerCase() === "y" || answer.toLowerCase() === "yes"); } private showToken(response: IHandlerResponseApi, tokenValue: string) { @@ -233,148 +211,45 @@ export abstract class BaseAuthHandler extends AbstractAuthHandler { } } - if (!ImperativeConfig.instance.config.exists) { - if (sessCfgWithCreds.tokenValue == null) { - // Provide dummy token information to prevent multiple V1 logout operations from failing - sessCfgWithCreds.type = SessConstants.AUTH_TYPE_TOKEN; - sessCfgWithCreds.tokenType = this.mDefaultTokenType; - sessCfgWithCreds.tokenValue = SessConstants.AUTH_TYPE_TOKEN; - } - this.mSession = new Session(sessCfgWithCreds); - await this.processLogoutOld(params); - } else { - const config = ImperativeConfig.instance.config; - const profileName = this.getBaseProfileName(params); - const profileProps = config.api.profiles.get(profileName, false); - let profileWithToken: string = null; - - let noDeleteReason = ""; - // If you specified a token on the command line, then don't delete the one in the profile if it doesn't match - if (Object.keys(profileProps).length > 0 && profileProps.tokenType != null && profileProps.tokenValue != null && - profileProps.tokenType === params.arguments.tokenType && profileProps.tokenValue === params.arguments.tokenValue) { - const profilePath = config.api.profiles.getProfilePathFromName(profileName); - config.delete(`${profilePath}.properties.tokenType`); - config.delete(`${profilePath}.properties.tokenValue`); - - await config.save(); - profileWithToken = profileName; - } else { - if (Object.keys(profileProps).length === 0) noDeleteReason = "Empty profile was provided."; - else if (profileProps.tokenType == null) noDeleteReason = "Token type was not provided."; - else if (profileProps.tokenValue == null) noDeleteReason = "Token value was not provided."; - else if (profileProps.tokenType !== params.arguments.tokenType) - noDeleteReason = "Token type does not match the authentication service"; - else if (profileProps.tokenValue !== params.arguments.tokenValue) - noDeleteReason = "Token value does not match the securely stored value"; - } - - if (params.arguments.tokenValue != null) { - let logoutMessage = "Logout successful. The authentication token has been revoked."; - if (logoutError?.errorCode === RestConstants.HTTP_STATUS_401.toString()) { - logoutMessage = "Token is not valid or expired."; - } - logoutMessage += `\nToken was${profileWithToken == null ? " not" : ""} removed from ` + - `your '${profileName}' ${this.mProfileType} profile.`; - logoutMessage += `${!noDeleteReason ? "" : "\nReason: " + noDeleteReason}`; - params.response.console.log(logoutMessage); - } else { - params.response.console.errorHeader("Command Error"); - params.response.console.error("Token was not provided, so can't log out."+ - "\nYou need to authenticate first using `zowe auth login`."); - params.response.data.setExitCode(1); - } - } - } - - /* Methods for old-school profiles below */ - private async processLoginOld(params: IHandlerParameters, tokenValue: string) { - // eslint-disable-next-line deprecation/deprecation - const loadedProfile = params.profiles.getMeta(this.mProfileType, false); + const config = ImperativeConfig.instance.config; + const profileName = this.getBaseProfileName(params); + const profileProps = config.api.profiles.get(profileName, false); let profileWithToken: string = null; - if (loadedProfile != null && loadedProfile.name != null) { - await Imperative.api.profileManager(this.mProfileType).update({ - name: loadedProfile.name, - args: { - "token-type": this.mSession.ISession.tokenType, - "token-value": tokenValue - }, - merge: true - }); - profileWithToken = loadedProfile.name; - } else { - - // Do not store non-profile arguments, user, or password. Set param arguments for prompted values from session. - - const copyArgs = {...params.arguments}; - copyArgs.createProfile = undefined; - copyArgs.showToken = undefined; - copyArgs.user = undefined; - copyArgs.password = undefined; - - copyArgs.host = this.mSession.ISession.hostname; - copyArgs.port = this.mSession.ISession.port; - - copyArgs.tokenType = this.mSession.ISession.tokenType; - copyArgs["token-type"] = this.mSession.ISession.tokenType; - - copyArgs.tokenValue = tokenValue; - copyArgs["token-value"] = tokenValue; - - const createParms: ISaveProfileFromCliArgs = { - name: "default", - type: this.mProfileType, - args: copyArgs, - overwrite: false, - profile: {} - }; - - if (await this.promptForBaseProfile(params, createParms.name)) { - await Imperative.api.profileManager(this.mProfileType).save(createParms); - profileWithToken = createParms.name; - } else { - this.showToken(params.response, tokenValue); - } - } + let noDeleteReason = ""; + // If you specified a token on the command line, then don't delete the one in the profile if it doesn't match + if (Object.keys(profileProps).length > 0 && profileProps.tokenType != null && profileProps.tokenValue != null && + profileProps.tokenType === params.arguments.tokenType && profileProps.tokenValue === params.arguments.tokenValue) { + const profilePath = config.api.profiles.getProfilePathFromName(profileName); + config.delete(`${profilePath}.properties.tokenType`); + config.delete(`${profilePath}.properties.tokenValue`); - if (profileWithToken != null) { - params.response.console.log(`\n` + - `Login successful. The authentication token is stored in the '${profileWithToken}' ` + - `${this.mProfileType} profile for future use. To revoke this token and remove it from your profile, review the ` + - `'zowe auth logout' command.`); + await config.save(); + profileWithToken = profileName; + } else { + if (Object.keys(profileProps).length === 0) noDeleteReason = "Empty profile was provided."; + else if (profileProps.tokenType == null) noDeleteReason = "Token type was not provided."; + else if (profileProps.tokenValue == null) noDeleteReason = "Token value was not provided."; + else if (profileProps.tokenType !== params.arguments.tokenType) + noDeleteReason = "Token type does not match the authentication service"; + else if (profileProps.tokenValue !== params.arguments.tokenValue) + noDeleteReason = "Token value does not match the securely stored value"; } - } - - private async processLogoutOld(params: IHandlerParameters) { - // eslint-disable-next-line deprecation/deprecation - const loadedProfile = params.profiles.getMeta(this.mProfileType, false); - // If you specified a token on the command line, then don't delete the one in the profile if it doesn't match - let profileWithToken: string = null; - if (loadedProfile != null && - loadedProfile.name != null && - loadedProfile.profile != null && - loadedProfile.profile.tokenValue != null && - params.arguments.tokenValue === loadedProfile.profile.tokenValue) { - await Imperative.api.profileManager(this.mProfileType).save({ - name: loadedProfile.name, - type: loadedProfile.type, - overwrite: true, - profile: { - ...loadedProfile.profile, - tokenType: undefined, - tokenValue: undefined - } - }); - profileWithToken = loadedProfile.name; + if (params.arguments.tokenValue != null) { + let logoutMessage = "Logout successful. The authentication token has been revoked."; + if (logoutError?.errorCode === RestConstants.HTTP_STATUS_401.toString()) { + logoutMessage = "Token is not valid or expired."; + } + logoutMessage += `\nToken was${profileWithToken == null ? " not" : ""} removed from ` + + `your '${profileName}' ${this.mProfileType} profile.`; + logoutMessage += `${!noDeleteReason ? "" : "\nReason: " + noDeleteReason}`; + params.response.console.log(logoutMessage); + } else { + params.response.console.errorHeader("Command Error"); + params.response.console.error("Token was not provided, so can't log out."+ + "\nYou need to authenticate first using `zowe auth login`."); + params.response.data.setExitCode(1); } - - this.mSession.ISession.type = SessConstants.AUTH_TYPE_BASIC; - this.mSession.ISession.tokenType = undefined; - this.mSession.ISession.tokenValue = undefined; - - params.response.console.log("Logout successful. The authentication token has been revoked" + - (profileWithToken != null ? ` and removed from your '${profileWithToken}' ${this.mProfileType} profile` : "") + - "."); } } diff --git a/packages/imperative/src/imperative/src/config/ConfigManagementFacility.ts b/packages/imperative/src/imperative/src/config/ConfigManagementFacility.ts index f24dcafe6e..22dd7ff124 100644 --- a/packages/imperative/src/imperative/src/config/ConfigManagementFacility.ts +++ b/packages/imperative/src/imperative/src/config/ConfigManagementFacility.ts @@ -62,7 +62,7 @@ export class ConfigManagementFacility { name: "config", type: "group", summary: "Manage JSON project and global configuration", - description: "Manage JSON project and global configuration", + description: "Manage JSON project and global configuration.", children: [ listDefinition, secureDefinition, diff --git a/packages/imperative/src/imperative/src/config/cmd/auto-init/AutoInitConstants.ts b/packages/imperative/src/imperative/src/config/cmd/auto-init/AutoInitConstants.ts index 5c04ee63fb..e5dbfd1e81 100644 --- a/packages/imperative/src/imperative/src/config/cmd/auto-init/AutoInitConstants.ts +++ b/packages/imperative/src/imperative/src/config/cmd/auto-init/AutoInitConstants.ts @@ -62,6 +62,18 @@ export class AutoInitConstants { group: AutoInitConstants.AUTO_INIT_OPTION_GROUP }; + /** + * Option used to override default editor + */ + public static AUTO_INIT_OPTION_EDITOR: ICommandOptionDefinition = { + name: "editor", + aliases: ["ed"], + description: `Editor that overrides the default editor for this file type. Set the option to the editor's executable file location ` + + `or the program's name: ie "--editor notepad"`, + type: "string", + implies: ["edit"] + }; + /** * Option used to specify whether or not to overwrite the config */ diff --git a/packages/imperative/src/imperative/src/config/cmd/auto-init/builders/AutoInitCommandBuilder.ts b/packages/imperative/src/imperative/src/config/cmd/auto-init/builders/AutoInitCommandBuilder.ts index 439c7386a6..fbcdc460ec 100644 --- a/packages/imperative/src/imperative/src/config/cmd/auto-init/builders/AutoInitCommandBuilder.ts +++ b/packages/imperative/src/imperative/src/config/cmd/auto-init/builders/AutoInitCommandBuilder.ts @@ -15,7 +15,7 @@ import { Logger } from "../../../../../../logger"; import { ICommandProfileAutoInitConfig } from "../../../../../../cmd/src/doc/profiles/definition/ICommandProfileAutoInitConfig"; import { ImperativeError } from "../../../../../../error"; import { TextUtils } from "../../../../../../utilities"; -import { autoInitCommandDesc } from "../../../../../../messages"; +import { autoInitCommandDesc, autoInitCommandSummary } from "../../../../../../messages"; import { Constants } from "../../../../../../constants"; import { AutoInitConstants } from "../AutoInitConstants"; @@ -85,19 +85,20 @@ export class AutoInitCommandBuilder implements AbstractCommandBuilder { AutoInitConstants.AUTO_INIT_OPTION_GLOBAL_CONFIG, AutoInitConstants.AUTO_INIT_OPTION_DRY_RUN, AutoInitConstants.AUTO_INIT_OPTION_EDIT, + AutoInitConstants.AUTO_INIT_OPTION_EDITOR, AutoInitConstants.AUTO_INIT_OPTION_OVERWRITE, AutoInitConstants.AUTO_INIT_OPTION_FOR_SURE, - ...(this.mConfig.autoInit?.options || []) + ...this.mConfig.autoInit?.options || [] ], examples: this.mConfig.autoInit?.examples, customize: {} }; if (autoInitCommand.summary == null) { - autoInitCommand.summary = TextUtils.formatMessage(autoInitCommandDesc.message, {source: this.mConfig.provider}); + autoInitCommand.summary = TextUtils.formatMessage(autoInitCommandSummary.message, {source: this.mConfig.provider}); } if (autoInitCommand.description == null) { - autoInitCommand.description = autoInitCommand.summary; + autoInitCommand.description = TextUtils.formatMessage(autoInitCommandDesc.message, {source: this.mConfig.provider}); } if (this.mProfileType != null) { autoInitCommand.profile = {}; diff --git a/packages/imperative/src/imperative/src/config/cmd/auto-init/handlers/BaseAutoInitHandler.ts b/packages/imperative/src/imperative/src/config/cmd/auto-init/handlers/BaseAutoInitHandler.ts index b3e0d249a0..c8b13bf27f 100644 --- a/packages/imperative/src/imperative/src/config/cmd/auto-init/handlers/BaseAutoInitHandler.ts +++ b/packages/imperative/src/imperative/src/config/cmd/auto-init/handlers/BaseAutoInitHandler.ts @@ -113,7 +113,8 @@ export abstract class BaseAutoInitHandler implements ICommandHandler { if (original.exists === false) { originalProperties = {}; } else { - originalProperties = JSONC.parse(JSONC.stringify(original.properties, null, ConfigConstants.INDENT)); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + originalProperties = JSONC.parse(JSONC.stringify(original.properties, null, ConfigConstants.INDENT)) as any; // Hide secure stuff for (const secureProp of ImperativeConfig.instance.config.api.secure.secureFields(original)) { @@ -124,7 +125,8 @@ export abstract class BaseAutoInitHandler implements ICommandHandler { } let dryRun: any = ImperativeConfig.instance.config.api.layers.merge(profileConfig, true); - const dryRunProperties = JSONC.parse(JSONC.stringify(dryRun.properties, null, ConfigConstants.INDENT)); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + const dryRunProperties = JSONC.parse(JSONC.stringify(dryRun.properties, null, ConfigConstants.INDENT)) as any; // Hide secure stuff for (const secureProp of ImperativeConfig.instance.config.api.secure.findSecure(dryRun.properties.profiles, "profiles")) { @@ -175,7 +177,7 @@ export abstract class BaseAutoInitHandler implements ICommandHandler { this.displayAutoInitChanges(params.response); if (params.arguments.edit && params.arguments.edit === true) { - await ProcessUtils.openInEditor(ImperativeConfig.instance.config.api.layers.get().path); + await ProcessUtils.openInEditor(ImperativeConfig.instance.config.api.layers.get().path, params.arguments.editor); } } } diff --git a/packages/imperative/src/imperative/src/config/cmd/convert-profiles/convert-profiles.definition.ts b/packages/imperative/src/imperative/src/config/cmd/convert-profiles/convert-profiles.definition.ts index 7b54f3294b..04c747bb89 100644 --- a/packages/imperative/src/imperative/src/config/cmd/convert-profiles/convert-profiles.definition.ts +++ b/packages/imperative/src/imperative/src/config/cmd/convert-profiles/convert-profiles.definition.ts @@ -22,7 +22,7 @@ export const convertProfilesDefinition: ICommandDefinition = { aliases: ["convert"], type: "command", handler: join(__dirname, "convert-profiles.handler"), - summary: "Convert profiles to team config", + summary: "Convert V1 profiles to a current Zowe client configuration", description: `Convert v1 profiles to a global ${ImperativeConfig.instance.rootCommandName}.config.json file.`, options: [{ name: "prompt", @@ -35,10 +35,10 @@ export const convertProfilesDefinition: ICommandDefinition = { type: "boolean" }], examples: [{ - description: "Convert profiles to team config without prompting", + description: "Convert V1 profiles to a new Zowe client configuration without prompting", options: "--no-prompt" }, { - description: "Convert profiles to team config and delete the old profiles", + description: "Convert V1 profiles to a new Zowe client configuration and delete the old V1 profiles", options: "--delete" }] }; diff --git a/packages/imperative/src/imperative/src/config/cmd/convert-profiles/convert-profiles.handler.ts b/packages/imperative/src/imperative/src/config/cmd/convert-profiles/convert-profiles.handler.ts index df0bf06fcc..943bf806df 100644 --- a/packages/imperative/src/imperative/src/config/cmd/convert-profiles/convert-profiles.handler.ts +++ b/packages/imperative/src/imperative/src/config/cmd/convert-profiles/convert-profiles.handler.ts @@ -9,307 +9,127 @@ * */ -import * as fs from "fs"; -import { removeSync } from "fs-extra"; -import * as path from "path"; -import { keyring as keytar } from "@zowe/secrets-for-zowe-sdk"; -import { ICommandHandler, IHandlerParameters } from "../../../../../cmd"; -import { ConfigBuilder, ConfigSchema } from "../../../../../config"; -import { ProfileIO, ProfileUtils } from "../../../../../profiles"; -import { ImperativeConfig } from "../../../../../utilities"; -import { AppSettings } from "../../../../../settings"; -import { PluginIssues } from "../../../plugins/utilities/PluginIssues"; +import { ICommandHandler, IHandlerParameters, IHandlerResponseConsoleApi } from "../../../../../cmd"; +import { + ConvertMsg, ConvertMsgFmt, ConvertV1Profiles, IConvertV1ProfOpts, IConvertV1ProfResult +} from "../../../../../config"; import { uninstall as uninstallPlugin } from "../../../plugins/utilities/npm-interface"; -import { OverridesLoader } from "../../../OverridesLoader"; -import { IImperativeOverrides } from "../../../doc/IImperativeOverrides"; - -interface IOldPluginInfo { - /** - * List of CLI plug-ins to uninstall - */ - plugins: string[]; - /** - * List of overrides to remove from app settings - */ - overrides: (keyof IImperativeOverrides)[]; -} - +import { TextUtils } from "../../../../../utilities"; /** * Handler for the convert profiles command. */ export default class ConvertProfilesHandler implements ICommandHandler { - private readonly ZOWE_CLI_PACKAGE_NAME = "@zowe/cli"; - private readonly ZOWE_CLI_SECURE_PLUGIN_NAME = "@zowe/secure-credential-store-for-zowe-cli"; - private keytar: typeof keytar = undefined; - /** - * Process the command and input. + * Process the command input and display output. * * @param {IHandlerParameters} params Parameters supplied by yargs * * @throws {ImperativeError} */ public async process(params: IHandlerParameters): Promise { - const cliBin = ImperativeConfig.instance.rootCommandName; - const profilesRootDir = ProfileUtils.constructProfilesRootDirectory(ImperativeConfig.instance.cliHome); - const configExists = ImperativeConfig.instance.config?.exists; - const oldPluginInfo = this.getOldPluginInfo(); - - // Cannot do profiles operations w/ team config - const oldProfileCount = configExists ? 0 : this.getOldProfileCount(profilesRootDir); - const oldProfilesDir = `${profilesRootDir.replace(/[\\/]$/, "")}-old`; - let skipConversion = false; - - if (configExists) { - // Warn that a team config was detected - params.response.console.log(`A team configuration file was detected. V1 profiles cannot be loaded for conversion.\n` + - `Run '${cliBin} config list --locations --root' for team configuration file locations.\n`); - } - - if (oldPluginInfo.plugins.length == 0 && oldProfileCount === 0) { - params.response.console.log("No old profiles were found to convert from Zowe v1 to v2."); - // Exit if we're not deleting - if (!(params.arguments.delete != null && params.arguments.delete === true)) { - return; - } else { - skipConversion = true; - } - } - - // If this is true, then we know that we want to delete, but there is nothing to convert first. - if (!skipConversion) { - if (oldProfileCount > 0) { - params.response.console.log(`Detected ${oldProfileCount} old profile(s) to convert from Zowe v1 to v2.\n`); - } - - if (oldPluginInfo.plugins.length > 0) { - params.response.console.log(`The following plug-ins will be removed because they are now part of the core CLI and are no longer ` + - `needed:\n\t${oldPluginInfo.plugins.join("\n\t")}\n`); - } + const convertOpts: IConvertV1ProfOpts = { + deleteV1Profs: false + }; + if (params.arguments?.delete) { + convertOpts.deleteV1Profs = true; if (params.arguments.prompt == null || params.arguments.prompt === true) { - const answer = await params.response.console.prompt("Are you sure you want to continue? [y/N]: "); - if (answer == null || !(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes")) { - return; - } - } - - params.response.console.log(""); - oldPluginInfo.overrides.forEach(this.removeOverride); - for (const pluginName of oldPluginInfo.plugins) { - try { - uninstallPlugin(pluginName); - params.response.console.log(`Uninstalled plug-in: ${pluginName}`); - } catch (error) { - params.response.console.error(`Failed to uninstall plug-in "${pluginName}":\n ${error}`); - } - } - - if (oldProfileCount != 0) { - await OverridesLoader.ensureCredentialManagerLoaded(); - - const convertResult = await ConfigBuilder.convert(profilesRootDir); - for (const [k, v] of Object.entries(convertResult.profilesConverted)) { - params.response.console.log(`Converted ${k} profiles: ${v.join(", ")}`); - } - if (convertResult.profilesFailed.length > 0) { - params.response.console.log(""); - params.response.console.errorHeader(`Failed to convert ${convertResult.profilesFailed.length} profile(s). See details below`); - for (const { name, type, error } of convertResult.profilesFailed) { - if (name != null) { - params.response.console.error(`Failed to load ${type} profile "${name}":\n ${error}`); - } else { - params.response.console.error(`Failed to find default ${type} profile:\n ${error}`); - } - } - } - - params.response.console.log(""); - const teamConfig = ImperativeConfig.instance.config; - teamConfig.api.layers.activate(false, true); - teamConfig.api.layers.merge(convertResult.config); - ConfigSchema.updateSchema(); - await teamConfig.save(); - - try { - fs.renameSync(profilesRootDir, oldProfilesDir); - } catch (error) { - params.response.console.error(`Failed to rename profiles directory to ${oldProfilesDir}:\n ${error}`); - } - - params.response.console.log(`Your new profiles have been saved to ${teamConfig.layerActive().path}.\n` + - `Run "${cliBin} config edit --global-config" to open this file in your default editor.\n`); - - if (params.arguments.delete == null || params.arguments.delete === false) { - params.response.console.log(`Your old profiles have been moved to ${oldProfilesDir}.\n` + - `Run "${cliBin} config convert-profiles --delete" if you want to completely remove them.\n\n` + - `If you would like to revert back to v1 profiles, or convert your v1 profiles again, rename the 'profiles-old' ` + - `directory to 'profiles' and delete the new config file located at ${teamConfig.layerActive().path}.`); + params.response.console.log( + "If you confirm the deletion of V1 profiles, they are deleted from disk after\n" + + "a successful conversion. Otherwise, they remain but are no longer used.\n" + + "You can also delete your V1 profiles later.\n" + ); + const answer = await params.response.console.prompt("Do you want to delete your V1 profiles now [y/N]: "); + if (answer.charAt(0).toLowerCase() !== "y") { + convertOpts.deleteV1Profs = false; } } } - if (params.arguments.delete != null && params.arguments.delete === true) { - if (params.arguments.prompt == null || params.arguments.prompt === true) { - const answer = await params.response.console.prompt("Are you sure you want to delete your v1 profiles? [y/N]: "); - if (answer == null || !(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes")) { - return; - } - } - - // Delete the profiles directory + const convertResult: IConvertV1ProfResult = await ConvertV1Profiles.convert(convertOpts); + + /* Uninstall the V1 SCS plugin. + * + * The uninstall cannot be done in ConvertV1Profiles.convert because circular + * dependencies cause problems in other unrelated modules that import from + * "@zowe/imperative". + * + * Add our messages to those already in the response object so that we can + * display all messages together later. + */ + if (convertResult.v1ScsPluginName) { try { - removeSync(oldProfilesDir); - params.response.console.log(`Deleting the profiles directory '${oldProfilesDir}'... done`); - } catch (err) { - params.response.console.error(`Failed to delete the profiles directory '${oldProfilesDir}':\n ${err}`); - } - - // Delete the securely stored credentials - const keytarAvailable = await this.checkKeytarAvailable(); - if (keytarAvailable) { - const knownServices = ["@brightside/core", "@zowe/cli", "Zowe-Plugin", "Broadcom-Plugin", "Zowe"]; - for (const service of knownServices) { - const accounts = await this.findOldSecureProps(service, params); - for (const account of accounts) { - if (!account.includes("secure_config_props")) { - const success = await this.deleteOldSecureProps(service, account, params); - params.response.console.log(`Deleting secure value for "${service}/${account}"... ${success ? "done" : "failed"}`); - } - } - } - } else { - params.response.console.error(`Keytar or the credential vault are unavailable. Unable to delete old secure values.`); - } - } - } - - /** - * Retrieve info about old plug-ins and their overrides. - * - `plugins` - List of CLI plug-ins to uninstall - * - `overrides` - List of overrides to remove from app settings - */ - private getOldPluginInfo(): IOldPluginInfo { - const pluginInfo: IOldPluginInfo = { - plugins: [], - overrides: [] - }; - - if (ImperativeConfig.instance.hostPackageName === this.ZOWE_CLI_PACKAGE_NAME) { - let oldCredMgr = AppSettings.instance.get("overrides", "CredentialManager"); - - if (typeof oldCredMgr !== "string" || oldCredMgr === ImperativeConfig.instance.hostPackageName) { - // Fall back to default plug-in name because CredentialManager override is not set - oldCredMgr = this.ZOWE_CLI_SECURE_PLUGIN_NAME; - } else { - // Need to remove CredentialManager override because it is a plug-in name - pluginInfo.overrides.push("CredentialManager"); - } - - // Only uninstall plug-in if it is currently installed - if (oldCredMgr in PluginIssues.instance.getInstalledPlugins()) { - pluginInfo.plugins.push(oldCredMgr); + uninstallPlugin(convertResult.v1ScsPluginName); + const newMsg = new ConvertMsg( + ConvertMsgFmt.REPORT_LINE | ConvertMsgFmt.PARAGRAPH, + `Successfully uninstalled plug-in ${convertResult.v1ScsPluginName}.` + ); + convertResult.msgs.push(newMsg); + } catch (error) { + let newMsg = new ConvertMsg( + ConvertMsgFmt.ERROR_LINE | ConvertMsgFmt.PARAGRAPH, + `Failed to uninstall plug-in ${convertResult.v1ScsPluginName}.` + ); + convertResult.msgs.push(newMsg); + + newMsg = new ConvertMsg( + ConvertMsgFmt.ERROR_LINE | ConvertMsgFmt.INDENT, error.message + ); + convertResult.msgs.push(newMsg); } } - return pluginInfo; - } - - /** - * Get the number of old profiles present in the CLI home dir. - * @param profilesRootDir Root profiles directory - * @returns Number of old profiles found - */ - private getOldProfileCount(profilesRootDir: string): number { - const profileTypes = ProfileIO.getAllProfileDirectories(profilesRootDir); - let oldProfileCount = 0; - for (const profileType of profileTypes) { - const profileTypeDir = path.join(profilesRootDir, profileType); - const profileNames = ProfileIO.getAllProfileNames(profileTypeDir, ".yaml", `${profileType}_meta`); - oldProfileCount += profileNames.length; - } - return oldProfileCount; + // show all report messages followed by error messages + this.showMsgsByType(convertResult.msgs, ConvertMsgFmt.REPORT_LINE, params.response.console); + this.showMsgsByType(convertResult.msgs, ConvertMsgFmt.ERROR_LINE, params.response.console); } /** - * Remove obsolete Imperative overrides from app settings. This method is - * called before uninstalling old plug-ins. + * Show all of the messages of a given type. + * The intent is to allow our caller to show a report of all actions, + * followed by a report of all errors. * - * This method is private because only the convert-profiles command is able - * to disable the credential manager and reload it. For all other commands, - * the credential manager is loaded in `Imperative.init` and frozen with - * `Object.freeze` so cannot be modified later on. + * @param setOfMsgs The available set of messages to display. + * @param msgTypeToShow The type of message to display. + * Either ConvertMsgFmt.REPORT_LINE or ConvertMsgFmt.ERROR_LINE. + * @param consoleApiFun The IHandlerResponseConsoleApi object used to display + * messages in a CLI terminal. */ - private removeOverride(override: keyof IImperativeOverrides) { - switch (override) { - case "CredentialManager": - AppSettings.instance.set("overrides", "CredentialManager", ImperativeConfig.instance.hostPackageName); - if (ImperativeConfig.instance.loadedConfig.overrides.CredentialManager != null) { - delete ImperativeConfig.instance.loadedConfig.overrides.CredentialManager; + private showMsgsByType( + setOfMsgs: ConvertMsg[], + msgTypeToShow: number, + consoleApiFun: IHandlerResponseConsoleApi + ): void { + + let firstMsgLine: boolean = true; + for (const nextMsg of setOfMsgs) { + let startingMsgText = ""; + if (nextMsg.msgFormat & msgTypeToShow) { + if (firstMsgLine) { + firstMsgLine = false; + if (msgTypeToShow & ConvertMsgFmt.ERROR_LINE) { + startingMsgText = "\nThe following operation(s) were not completed:\n"; + } + + // We want one newline before our first message, but avoid a double newline + if (!(nextMsg.msgFormat & ConvertMsgFmt.PARAGRAPH)) { + startingMsgText += "\n"; + } } - break; - } - } - /** - * Lazy load keytar, and verify that the credential vault is able to be accessed, - * or whether there is a problem. - * @returns true if credential vault is available, false if it is not - */ - private async checkKeytarAvailable(): Promise { - let success: boolean = false; - const requireOpts: any = {}; - // eslint-disable-next-line deprecation/deprecation - if (process.mainModule?.filename != null) { - // eslint-disable-next-line deprecation/deprecation - requireOpts.paths = [process.mainModule.filename]; - } - try { - const keytarPath = require.resolve("@zowe/secrets-for-zowe-sdk", requireOpts); - this.keytar = (await import(keytarPath)).keyring; - await this.keytar.findCredentials(this.ZOWE_CLI_PACKAGE_NAME); - success = true; - } catch (err) { - success = false; - } - return success; - } + if (nextMsg.msgFormat & ConvertMsgFmt.PARAGRAPH) { + startingMsgText += "\n"; + } + if (nextMsg.msgFormat & ConvertMsgFmt.INDENT) { + startingMsgText += " "; + } - /** - * Locate the names of secured properties stored under an account in the operating - * system's credential vault. - * @param acct The account to search for in the credential store - * @param params The parameters and response console APIs - * @returns a list of secured properties stored under the specified account - */ - private async findOldSecureProps(acct: string, params: IHandlerParameters): Promise { - const oldSecurePropNames: string[] = []; - try { - const credentialsArray = await this.keytar.findCredentials(acct); - for (const element of credentialsArray) { - oldSecurePropNames.push(element.account); + if (msgTypeToShow & ConvertMsgFmt.REPORT_LINE) { + consoleApiFun.log(startingMsgText + nextMsg.msgText); + } else { + consoleApiFun.error(TextUtils.chalk.red(startingMsgText + nextMsg.msgText)); + } } - } catch (err) { - params.response.console.error(`Encountered an error while gathering profiles for service '${acct}':\n ${err}`); - } - return oldSecurePropNames; - } - - /** - * Delete the secure property specified from the operating system credential vault. - * @param acct The account the property is stored under - * @param propName The name of the property to delete - * @param params The parameters and response console APIs - * @returns true if the property was deleted successfully - */ - private async deleteOldSecureProps(acct: string, propName: string, params: IHandlerParameters): Promise { - let success = false; - try { - success = await this.keytar.deletePassword(acct, propName); - } catch (err) { - params.response.console.error(`Encountered an error while deleting secure data for service '${acct}/${propName}':\n ${err}`); - success = false; } - return success; } } diff --git a/packages/imperative/src/imperative/src/config/cmd/edit/edit.definition.ts b/packages/imperative/src/imperative/src/config/cmd/edit/edit.definition.ts index 980b4f2166..56c82804f4 100644 --- a/packages/imperative/src/imperative/src/config/cmd/edit/edit.definition.ts +++ b/packages/imperative/src/imperative/src/config/cmd/edit/edit.definition.ts @@ -11,7 +11,6 @@ import { ICommandDefinition } from "../../../../../cmd"; import { join } from "path"; -import { ImperativeConfig } from "../../../../../utilities/src/ImperativeConfig"; /** * Definition of the edit command. @@ -21,11 +20,10 @@ export const editDefinition: ICommandDefinition = { name: "edit", type: "command", handler: join(__dirname, "edit.handler"), - summary: "edit config files", + summary: "Edit config files", description: `Edit an existing config file in your system's default text editor.\n\n` + `In a graphical environment, the application associated with JSON files will be launched. ` + - `In a command-line environment, vi will be launched. To override the command-line editor used, specify it in ` + - `the ${ImperativeConfig.instance.loadedConfig.envVariablePrefix}_EDITOR environment variable.`, + `In a command-line environment, vi will be launched. To override the command-line editor used, specify it with the --editor option.`, options: [ { name: "global-config", @@ -40,7 +38,15 @@ export const editDefinition: ICommandDefinition = { aliases: ["uc"], type: "boolean", defaultValue: false - } + }, + { + name: "editor", + description: `Editor that overrides the default editor for this file type. Set the option to the editor's executable file location ` + + `or the program's name: ie "--editor notepad".`, + aliases: ["ed"], + type: "string", + required: false + }, ], examples: [ { diff --git a/packages/imperative/src/imperative/src/config/cmd/edit/edit.handler.ts b/packages/imperative/src/imperative/src/config/cmd/edit/edit.handler.ts index fbd05c5694..ec7ed8e733 100644 --- a/packages/imperative/src/imperative/src/config/cmd/edit/edit.handler.ts +++ b/packages/imperative/src/imperative/src/config/cmd/edit/edit.handler.ts @@ -34,7 +34,7 @@ export default class EditHandler implements ICommandHandler { params.response.console.log(`File does not exist: ${configLayer.path}\n` + `To create it, run "${ImperativeConfig.instance.rootCommandName} ${initCmd}".`); } else { - await ProcessUtils.openInEditor(ImperativeConfig.instance.config.api.layers.get().path); + await ProcessUtils.openInEditor(ImperativeConfig.instance.config.api.layers.get().path, params.arguments.editor); } } } diff --git a/packages/imperative/src/imperative/src/config/cmd/import/import.definition.ts b/packages/imperative/src/imperative/src/config/cmd/import/import.definition.ts index b7ce72c79f..473021c773 100644 --- a/packages/imperative/src/imperative/src/config/cmd/import/import.definition.ts +++ b/packages/imperative/src/imperative/src/config/cmd/import/import.definition.ts @@ -22,7 +22,7 @@ export const importDefinition: ICommandDefinition = { name: "import", type: "command", handler: join(__dirname, "import.handler"), - summary: "import config files", + summary: "Import config files", description: "Import config files from another location on disk or from an Internet URL.\n\n" + "If the config `$schema` property points to a relative path, the schema will also be imported.", positionals: [ diff --git a/packages/imperative/src/imperative/src/config/cmd/import/import.handler.ts b/packages/imperative/src/imperative/src/config/cmd/import/import.handler.ts index 5d9d4791e6..a6f82ba382 100644 --- a/packages/imperative/src/imperative/src/config/cmd/import/import.handler.ts +++ b/packages/imperative/src/imperative/src/config/cmd/import/import.handler.ts @@ -49,8 +49,9 @@ export default class ImportHandler implements ICommandHandler { const configFilePath = path.resolve(params.arguments.location); const isConfigLocal = fs.existsSync(configFilePath) || path.isAbsolute(params.arguments.location); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 const configJson: IConfig = isConfigLocal ? - JSONC.parse(fs.readFileSync(configFilePath, "utf-8")) : + JSONC.parse(fs.readFileSync(configFilePath, "utf-8")) as any : await this.fetchConfig(new URL(params.arguments.location)); config.api.layers.set(configJson); @@ -102,7 +103,8 @@ export default class ImportHandler implements ICommandHandler { private async fetchConfig(url: URL): Promise { const response = await RestClient.getExpectString(this.buildSession(url), url.pathname); try { - return JSONC.parse(response); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + return JSONC.parse(response) as any; } catch (error) { throw new ImperativeError({ msg: "Failed to parse config JSON: URL must point to a valid JSON file\n" + error.message, @@ -122,7 +124,8 @@ export default class ImportHandler implements ICommandHandler { } else { const response = await RestClient.getExpectString(this.buildSession(url), url.pathname); try { - JSONC.parse(response); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + JSONC.parse(response) as any; } catch (error) { throw new ImperativeError({ msg: "Failed to parse schema JSON: URL must point to a valid JSON file\n" + error.message, diff --git a/packages/imperative/src/imperative/src/config/cmd/init/init.definition.ts b/packages/imperative/src/imperative/src/config/cmd/init/init.definition.ts index de92250002..0b0e0c0239 100644 --- a/packages/imperative/src/imperative/src/config/cmd/init/init.definition.ts +++ b/packages/imperative/src/imperative/src/config/cmd/init/init.definition.ts @@ -21,7 +21,7 @@ export const initDefinition: ICommandDefinition = { name: "init", type: "command", handler: join(__dirname, "init.handler"), - summary: "init config files", + summary: "Init config files", description: `Initialize config files. Defaults to initializing "${ImperativeConfig.instance.rootCommandName}.config.json" in the current ` + `working directory unless otherwise specified.\n\nUse "--user-config" to init ` + `"${ImperativeConfig.instance.rootCommandName}.config.user.json". Use "--global-config" to initialize the configuration files in your home ` + @@ -72,9 +72,17 @@ export const initDefinition: ICommandDefinition = { { name: "edit", aliases: ["e"], - description: "Open in editor after initializing the configuration", + description: "Open in editor after initializing the configuration.", type: "boolean", conflictsWith: ["dry-run"] + }, + { + name: "editor", + description: `Editor that overrides the default editor for this file type. Set the option to the editor's executable file location ` + + `or the program's name: ie "--editor notepad".`, + aliases: ["ed"], + type: "string", + implies: ["edit"] } ], examples: [ diff --git a/packages/imperative/src/imperative/src/config/cmd/init/init.handler.ts b/packages/imperative/src/imperative/src/config/cmd/init/init.handler.ts index ae3d298af3..6370a4a3b0 100644 --- a/packages/imperative/src/imperative/src/config/cmd/init/init.handler.ts +++ b/packages/imperative/src/imperative/src/config/cmd/init/init.handler.ts @@ -47,13 +47,14 @@ export default class InitHandler implements ICommandHandler { // Load the config and set the active layer according to user options await OverridesLoader.ensureCredentialManagerLoaded(); const config = ImperativeConfig.instance.config; - const configDir = params.arguments.globalConfig ? null : process.cwd(); - config.api.layers.activate(params.arguments.userConfig, params.arguments.globalConfig, configDir); + const globalConfig: boolean = params.arguments?.globalConfig ? true : false; + const configDir = globalConfig ? null : process.cwd(); + config.api.layers.activate(params.arguments.userConfig, globalConfig, configDir); const layer = config.api.layers.get(); // Do a dry run if dryRun flag is present. Otherwise, initialize or overwrite the config if (params.arguments.dryRun && params.arguments.dryRun === true) { - let dryRun = await this.initForDryRun(config, params.arguments.userConfig); + let dryRun = await this.initForDryRun(config, params.arguments.userConfig, globalConfig); // Merge and display, do not save // Handle if the file doesn't actually exist @@ -63,7 +64,8 @@ export default class InitHandler implements ICommandHandler { if (original.exists === false) { originalProperties = {}; } else { - originalProperties = JSONC.parse(JSONC.stringify(original.properties, null, ConfigConstants.INDENT)); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + originalProperties = JSONC.parse(JSONC.stringify(original.properties, null, ConfigConstants.INDENT)) as any; // Hide secure stuff for (const secureProp of ImperativeConfig.instance.config.api.secure.secureFields(original)) { @@ -72,8 +74,8 @@ export default class InitHandler implements ICommandHandler { } } } - - const dryRunProperties = JSONC.parse(JSONC.stringify(dryRun.properties, null, ConfigConstants.INDENT)); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + const dryRunProperties = JSONC.parse(JSONC.stringify(dryRun.properties, null, ConfigConstants.INDENT)) as any; // Hide secure stuff for (const secureProp of ImperativeConfig.instance.config.api.secure.findSecure(dryRun.properties.profiles, "profiles")) { @@ -99,12 +101,17 @@ export default class InitHandler implements ICommandHandler { params.response.console.log(jsonDiff); params.response.data.setObj(jsonDiff); } else { - await this.initWithSchema(config, params.arguments.userConfig, params.arguments.overwrite && params.arguments.forSure); + await this.initWithSchema(config, params.arguments.userConfig, globalConfig, params.arguments.overwrite && params.arguments.forSure); if (params.arguments.prompt !== false && config.api.secure.loadFailed && config.api.secure.secureFields().length > 0) { const warning = ConfigUtils.secureSaveError(); - params.response.console.log(TextUtils.chalk.yellow("Warning:\n") + - `${warning.message} Skipped prompting for credentials.\n\n${warning.additionalDetails}\n`); + let message = "Warning:\n" + warning.message + " Skipped prompting for credentials."; + + if (warning.additionalDetails) { + message += `\n\n${warning.additionalDetails}\n`; + } + + params.response.console.log(TextUtils.chalk.yellow(message)); } // Write the active created/updated config layer @@ -112,7 +119,7 @@ export default class InitHandler implements ICommandHandler { params.response.console.log(`Saved config template to ${layer.path}`); if (params.arguments.edit && params.arguments.edit === true) { - await ProcessUtils.openInEditor(ImperativeConfig.instance.config.api.layers.get().path); + await ProcessUtils.openInEditor(ImperativeConfig.instance.config.api.layers.get().path, params.arguments.editor); } } } @@ -122,8 +129,10 @@ export default class InitHandler implements ICommandHandler { * folder alongside the config. * @param config Config object to be populated * @param user If true, properties will be left empty for user config + * @param globalConfig Is the config to be a global config? + * @param overwrite Shall we overwrite an existing config? */ - private async initWithSchema(config: Config, user: boolean, overwrite: boolean): Promise { + private async initWithSchema(config: Config, user: boolean, globalConfig: boolean, overwrite: boolean): Promise { const opts: IConfigBuilderOpts = {}; if (!user) { opts.populateProperties = true; @@ -131,17 +140,18 @@ export default class InitHandler implements ICommandHandler { } // Build new config and merge with existing layer or overwrite it if overwrite & forSure options are present - const newConfig: IConfig = await ConfigBuilder.build(ImperativeConfig.instance.loadedConfig, opts); + const newConfig: IConfig = await ConfigBuilder.build(ImperativeConfig.instance.loadedConfig, globalConfig, opts); if (overwrite) { config.api.layers.set(newConfig); } else { const oldConfig = config.layerActive().properties; - if (oldConfig.profiles.base?.properties != null) { + const baseProfileNm: string = ConfigUtils.formGlobOrProjProfileNm("base", globalConfig); + if (oldConfig.profiles[baseProfileNm]?.properties != null) { // Remove values that should be overwritten from old base profile - for (const propName of Object.keys(oldConfig.profiles.base.properties)) { - const newPropValue = newConfig.profiles.base.properties[propName]; + for (const propName of Object.keys(oldConfig.profiles[baseProfileNm].properties)) { + const newPropValue = newConfig.profiles[baseProfileNm].properties[propName]; if (this.promptProps.includes(propName) && newPropValue != null && newPropValue !== "") { - delete oldConfig.profiles.base.properties[propName]; + delete oldConfig.profiles[baseProfileNm].properties[propName]; } } } @@ -157,15 +167,16 @@ export default class InitHandler implements ICommandHandler { * Also create a schema file in the same folder alongside the config. * @param config Config object to be populated * @param user If true, properties will be left empty for user config + * @param globalConfig Is the config to be a global config? */ - private async initForDryRun(config: Config, user: boolean): Promise { + private async initForDryRun(config: Config, user: boolean, globalConfig: boolean): Promise { const opts: IConfigBuilderOpts = {}; if (!user) { opts.populateProperties = true; } // Build new config and merge with existing layer - const newConfig: IConfig = await ConfigBuilder.build(ImperativeConfig.instance.loadedConfig, opts); + const newConfig: IConfig = await ConfigBuilder.build(ImperativeConfig.instance.loadedConfig, globalConfig, opts); return config.api.layers.merge(newConfig, true); } diff --git a/packages/imperative/src/imperative/src/config/cmd/list/list.definition.ts b/packages/imperative/src/imperative/src/config/cmd/list/list.definition.ts index ea684df2fb..d6ff92e795 100644 --- a/packages/imperative/src/imperative/src/config/cmd/list/list.definition.ts +++ b/packages/imperative/src/imperative/src/config/cmd/list/list.definition.ts @@ -16,8 +16,8 @@ export const listDefinition: ICommandDefinition = { name: "list", aliases: ["ls"], type: "command", - summary: "list config properties", - description: "List config properties", + summary: "List config properties", + description: "List config properties.", handler: join(__dirname, "list.handler"), positionals: [ { @@ -34,10 +34,13 @@ export const listDefinition: ICommandDefinition = { type: "boolean" }, { - name: "root", - description: "List only the root level property names. " + + name: "name-only", + description: "List only the names of root level property names. " + "For example, specify in addition to '--locations' to get a list of config file paths only.", - type: "boolean" + type: "boolean", + aliases: [ + "root" + ] } ], examples: [ @@ -47,7 +50,7 @@ export const listDefinition: ICommandDefinition = { }, { description: "List only root level property names for a specified config property", - options: `"defaults" --root` + options: `"defaults" --name-only` }, { description: "List config properties by separating them by their respective config file locations", @@ -55,11 +58,11 @@ export const listDefinition: ICommandDefinition = { }, { description: "List only the root level configuration property names", - options: "--root" + options: "--name-only" }, { - description: "List only the root level configuration properties by separating them by their respective config file locations", - options: "--locations --root" + description: "List only the root level configuration property names by separating them by their respective config file locations", + options: "--locations --name-only" } ] }; diff --git a/packages/imperative/src/imperative/src/config/cmd/list/list.handler.ts b/packages/imperative/src/imperative/src/config/cmd/list/list.handler.ts index 6198922be5..47b83fc810 100644 --- a/packages/imperative/src/imperative/src/config/cmd/list/list.handler.ts +++ b/packages/imperative/src/imperative/src/config/cmd/list/list.handler.ts @@ -51,8 +51,8 @@ export default class ListHandler implements ICommandHandler { } } - // If requested, only include the root property - if (params.arguments.root && lodash.isObject(obj)) { + // If requested, only include the root property name + if (params.arguments.nameOnly && lodash.isObject(obj)) { obj = Object.keys(obj); } @@ -60,7 +60,7 @@ export default class ListHandler implements ICommandHandler { params.response.data.setObj(obj); params.response.format.output({ output: obj, - format: (Array.isArray(obj)) ? "list" : "object" + format: Array.isArray(obj) ? "list" : "object" }); } } diff --git a/packages/imperative/src/imperative/src/config/cmd/profiles/profiles.definition.ts b/packages/imperative/src/imperative/src/config/cmd/profiles/profiles.definition.ts index 1c61041002..0da5f5e8f6 100644 --- a/packages/imperative/src/imperative/src/config/cmd/profiles/profiles.definition.ts +++ b/packages/imperative/src/imperative/src/config/cmd/profiles/profiles.definition.ts @@ -20,7 +20,7 @@ export const profilesDefinition: ICommandDefinition = { name: "profiles", type: "command", handler: join(__dirname, "profiles.handler"), - summary: "displays profile paths", + summary: "Displays profile paths", description: "Displays profile paths.", examples: [ { diff --git a/packages/imperative/src/imperative/src/config/cmd/report-env/EnvItems.ts b/packages/imperative/src/imperative/src/config/cmd/report-env/EnvItems.ts index bd5a9f8344..bf72572e61 100644 --- a/packages/imperative/src/imperative/src/config/cmd/report-env/EnvItems.ts +++ b/packages/imperative/src/imperative/src/config/cmd/report-env/EnvItems.ts @@ -18,7 +18,6 @@ export enum ItemId { ZOWE_VER, NODEJS_VER, - NVM_VER, PLATFORM, ARCHITECTURE, OS_PATH, @@ -27,7 +26,7 @@ export enum ItemId { ZOWE_IMPERATIVE_LOG_LEVEL, OTHER_ZOWE_VARS, // Zowe variables not listed above NPM_VER, - ZOWE_CONFIG_TYPE, // detect if we have V1 profiles or V2 config + ZOWE_CONFIG_INFO, ZOWE_PLUGINS } diff --git a/packages/imperative/src/imperative/src/config/cmd/report-env/EnvQuery.ts b/packages/imperative/src/imperative/src/config/cmd/report-env/EnvQuery.ts index 577b7100a0..70cc2a614c 100644 --- a/packages/imperative/src/imperative/src/config/cmd/report-env/EnvQuery.ts +++ b/packages/imperative/src/imperative/src/config/cmd/report-env/EnvQuery.ts @@ -9,7 +9,6 @@ * */ -import * as fs from "fs"; import * as os from "os"; import * as lodash from "lodash"; import * as path from "path"; @@ -18,7 +17,6 @@ import { StdioOptions } from "child_process"; import { ConfigConstants, IConfigProfile } from "../../../../../config"; import { IHandlerProgressApi } from "../../../../../cmd"; -import { IO } from "../../../../../io"; import { ImperativeConfig , TextUtils } from "../../../../../utilities"; import { ITaskWithStatus, TaskProgress, TaskStage } from "../../../../../operations"; import { CliUtils } from "../../../../../utilities/src/CliUtils"; @@ -83,11 +81,6 @@ export class EnvQuery { getResult.itemValMsg = "Node.js version = " + getResult.itemVal; break; } - case ItemId.NVM_VER: { - getResult.itemVal = EnvQuery.getCmdOutput("nvm", ["version"]); - getResult.itemValMsg = "Node Version Manager version = " + getResult.itemVal; - break; - } case ItemId.PLATFORM: { getResult.itemVal = os.platform(); getResult.itemValMsg = "O.S. platform = " + getResult.itemVal; @@ -130,7 +123,7 @@ export class EnvQuery { await EnvQuery.getNpmInfo(getResult, getItemOpts); break; } - case ItemId.ZOWE_CONFIG_TYPE: { + case ItemId.ZOWE_CONFIG_INFO: { await EnvQuery.getConfigInfo(getResult, getItemOpts); break; } @@ -218,9 +211,8 @@ export class EnvQuery { private static async getConfigInfo( getResult: IGetItemVal, getItemOpts: IGetItemOpts ): Promise { - const teamCfg: string = "V2 Team Config"; - const v1Profiles = "V1 Profiles"; - const doesProgBarExist: boolean = (getItemOpts?.progressApi) ? true: false; + const teamCfg: string = "Zowe Client Config"; + const doesProgBarExist: boolean = getItemOpts?.progressApi ? true: false; // setup progress bar const configProgress: ITaskWithStatus = { @@ -231,12 +223,8 @@ export class EnvQuery { if (ImperativeConfig.instance.config?.exists) { getResult.itemVal = teamCfg; - configProgress.statusMessage = "Retrieving V2 configuration"; + configProgress.statusMessage = "Retrieving Zowe client configuration"; configProgress.percentComplete = TaskProgress.TWENTY_PERCENT; - } else { - getResult.itemVal = v1Profiles; - configProgress.statusMessage = "Retrieving V1 configuration"; - configProgress.percentComplete = TaskProgress.FIFTY_PERCENT; } if (doesProgBarExist) { @@ -262,11 +250,10 @@ export class EnvQuery { } else { getResult.itemValMsg += "off"; } - getResult.itemValMsg += `${os.EOL}Zowe config type = ` + getResult.itemVal; if ( getResult.itemVal == teamCfg) { // Display all relevant zowe team config files. - configProgress.statusMessage = "Retrieving active team config files"; + configProgress.statusMessage = "Retrieving active Zowe client config files"; configProgress.percentComplete = TaskProgress.THIRTY_PERCENT; await EnvQuery.updateProgressBar(doesProgBarExist); const config = ImperativeConfig.instance.config; @@ -288,7 +275,7 @@ export class EnvQuery { } } - getResult.itemValMsg += `${os.EOL}Team config files in effect:${os.EOL}`; + getResult.itemValMsg += `${os.EOL}Zowe client config files in use:${os.EOL}`; for (const configLoc of Object.keys(configListObj)) { getResult.itemValMsg += EnvQuery.indent + configLoc + os.EOL; } @@ -302,7 +289,7 @@ export class EnvQuery { let maxSpace: number = 1; for (const profType of Object.keys(config.mProperties.defaults)) { // calculate the max space we need between profile type and name - maxSpace = (maxSpace < profType.length) ? profType.length + 1 : maxSpace; + maxSpace = maxSpace < profType.length ? profType.length + 1 : maxSpace; } for (const profType of Object.keys(config.mProperties.defaults)) { getResult.itemValMsg += EnvQuery.indent + profType + " ="; @@ -341,40 +328,7 @@ export class EnvQuery { getResult.itemValMsg += EnvQuery.indent + profPathNm + os.EOL; } } else { - // display V1 profile information - configProgress.statusMessage = "Retrieving available profile names"; - configProgress.percentComplete = TaskProgress.NINETY_PERCENT; - await EnvQuery.updateProgressBar(doesProgBarExist); - - getResult.itemValMsg += `${os.EOL}Available profiles:${os.EOL}`; - const v1ProfilesDir = path.normalize(ImperativeConfig.instance.cliHome + "/profiles"); - if (IO.isDir(v1ProfilesDir)) { - // read all of the subdirectories of the profiles directory - fs.readdirSync(v1ProfilesDir).forEach((nextProfileTypeNm) => { - const profileTypeDir = path.normalize(v1ProfilesDir + "/" + nextProfileTypeNm); - let profilesOfCurrType: string = ""; - - // is the next candidate for nextProfileTypeNm a directory? - if (IO.isDir(profileTypeDir)) { - // does the next profile type directory have any profiles? - fs.readdirSync(profileTypeDir).forEach((nextProfileNm) => { - // exclude the meta files - if (nextProfileNm.endsWith("_meta.yaml")) { - return; - } - profilesOfCurrType += EnvQuery.indent + EnvQuery.indent + - nextProfileNm.replace(".yaml", "") + os.EOL; - }); - } - - // did we find any profiles? - if (profilesOfCurrType.length > 0) { - getResult.itemValMsg += EnvQuery.indent + nextProfileTypeNm + - " profiles: " + os.EOL + profilesOfCurrType; - - } - }); - } + getResult.itemValMsg += `${os.EOL}No Zowe client configuration detected.${os.EOL}`; } // add indent to each line @@ -427,7 +381,7 @@ export class EnvQuery { getItemOpts: IGetItemOpts ): Promise { const percentIncr: number = 10; - const doesProgBarExist: boolean = (getItemOpts?.progressApi) ? true: false; + const doesProgBarExist: boolean = getItemOpts?.progressApi ? true: false; // setup progress bar const npmProgress: ITaskWithStatus = { @@ -557,7 +511,7 @@ export class EnvQuery { private static async getPluginInfo( getResult: IGetItemVal, getItemOpts: IGetItemOpts ): Promise { - const doesProgBarExist: boolean = (getItemOpts?.progressApi) ? true: false; + const doesProgBarExist: boolean = getItemOpts?.progressApi ? true: false; // setup progress bar const configProgress: ITaskWithStatus = { diff --git a/packages/imperative/src/imperative/src/config/cmd/report-env/Report-env.definition.ts b/packages/imperative/src/imperative/src/config/cmd/report-env/Report-env.definition.ts index b1775d9019..8411ebf4f3 100644 --- a/packages/imperative/src/imperative/src/config/cmd/report-env/Report-env.definition.ts +++ b/packages/imperative/src/imperative/src/config/cmd/report-env/Report-env.definition.ts @@ -22,7 +22,7 @@ export const ReportEnvDefinition: ICommandDefinition = { type: "command", handler: join(__dirname, "Report-env.handler"), summary: "Report the state of your working environment", - description: "Reports key items from your environment and identifies problem conditions", + description: "Reports key items from your environment and identifies problem conditions.", examples: [ { description: "Report information and issues about your working environment", diff --git a/packages/imperative/src/imperative/src/config/cmd/report-env/Report-env.handler.ts b/packages/imperative/src/imperative/src/config/cmd/report-env/Report-env.handler.ts index 9b3005f989..21139e523f 100644 --- a/packages/imperative/src/imperative/src/config/cmd/report-env/Report-env.handler.ts +++ b/packages/imperative/src/imperative/src/config/cmd/report-env/Report-env.handler.ts @@ -45,7 +45,7 @@ export default class ReportEnvHandler implements ICommandHandler { )) { // These items have a progress bar. Output a newline beforehand. - if (nextItemId == ItemId.NPM_VER || nextItemId == ItemId.ZOWE_CONFIG_TYPE) { + if (nextItemId == ItemId.NPM_VER || nextItemId == ItemId.ZOWE_CONFIG_INFO) { responseApi.console.error(EOL); } await this.displayEnvItem(nextItemId, responseApi); diff --git a/packages/imperative/src/imperative/src/config/cmd/schema/schema.definition.ts b/packages/imperative/src/imperative/src/config/cmd/schema/schema.definition.ts index ebde972f8e..e902517642 100644 --- a/packages/imperative/src/imperative/src/config/cmd/schema/schema.definition.ts +++ b/packages/imperative/src/imperative/src/config/cmd/schema/schema.definition.ts @@ -20,7 +20,7 @@ export const schemaDefinition: ICommandDefinition = { name: "schema", type: "command", handler: join(__dirname, "schema.handler"), - summary: "dumps the JSON schema for the config", + summary: "Dumps the JSON schema for the config", description: "Dumps the JSON schema for the config. " + "The schema is dynamically created based on your available plugins. " + "Direct the output of this command to a file and include in your config with '$schema' property to get editor completion.", diff --git a/packages/imperative/src/imperative/src/config/cmd/secure/secure.definition.ts b/packages/imperative/src/imperative/src/config/cmd/secure/secure.definition.ts index b903c48be0..db10cab504 100644 --- a/packages/imperative/src/imperative/src/config/cmd/secure/secure.definition.ts +++ b/packages/imperative/src/imperative/src/config/cmd/secure/secure.definition.ts @@ -16,8 +16,8 @@ export const secureDefinition: ICommandDefinition = { name: "secure", type: "command", handler: join(__dirname, "secure.handler"), - summary: "secure configuration properties", - description: "prompt for secure configuration properties", + summary: "Secure configuration properties", + description: "Prompt for secure configuration properties.", options: [ { name: "global-config", @@ -35,7 +35,7 @@ export const secureDefinition: ICommandDefinition = { }, { name: "prune", - description: "Delete properties stored in the vault for team config files that do not exist.", + description: "Delete properties stored in the vault for Zowe client config files that do not exist.", aliases: ["p"], type: "boolean", defaultValue: false diff --git a/packages/imperative/src/imperative/src/config/cmd/secure/secure.handler.ts b/packages/imperative/src/imperative/src/config/cmd/secure/secure.handler.ts index 9398585097..582be79f75 100644 --- a/packages/imperative/src/imperative/src/config/cmd/secure/secure.handler.ts +++ b/packages/imperative/src/imperative/src/config/cmd/secure/secure.handler.ts @@ -10,7 +10,8 @@ */ import { ICommandArguments, ICommandHandler, IHandlerParameters } from "../../../../../cmd"; -import { Config, ConfigAutoStore, ConfigConstants, ConfigSchema } from "../../../../../config"; +import { Config, ConfigConstants, ConfigSchema } from "../../../../../config"; +import { ConfigAutoStore } from "../../../../../config/src/ConfigAutoStore"; import { ConfigUtils } from "../../../../../config/src/ConfigUtils"; import { ImperativeError } from "../../../../../error"; import { Logger } from "../../../../../logger"; diff --git a/packages/imperative/src/imperative/src/config/cmd/set/set.definition.ts b/packages/imperative/src/imperative/src/config/cmd/set/set.definition.ts index b151990336..b340482dcb 100644 --- a/packages/imperative/src/imperative/src/config/cmd/set/set.definition.ts +++ b/packages/imperative/src/imperative/src/config/cmd/set/set.definition.ts @@ -16,12 +16,12 @@ export const setDefinition: ICommandDefinition = { name: "set", type: "command", handler: join(__dirname, "set.handler"), - summary: "set configuration property", - description: "create or update a configuration property", + summary: "Set configuration property", + description: "Create or update a configuration property.", positionals: [ { name: "property", - description: "The property to set. You may specify a path using dot notation (e.g. profiles.host1.profiles.service1.properties.setting)", + description: "The property to set. You may specify a path using dot notation (e.g. profiles.host1.profiles.service1.properties.setting).", required: true, type: "string" }, diff --git a/packages/imperative/src/imperative/src/config/cmd/set/set.handler.ts b/packages/imperative/src/imperative/src/config/cmd/set/set.handler.ts index 9b5fb96324..3581c86df4 100644 --- a/packages/imperative/src/imperative/src/config/cmd/set/set.handler.ts +++ b/packages/imperative/src/imperative/src/config/cmd/set/set.handler.ts @@ -52,7 +52,8 @@ export default class SetHandler implements ICommandHandler { if (params.arguments.json) { try { - value = JSONC.parse(value, null, true); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + value = JSONC.parse(value, null, true) as any; } catch (e) { throw new ImperativeError({ msg: `could not parse JSON value: ${e.message}` }); } diff --git a/packages/imperative/src/imperative/src/config/cmd/update-schemas/update-schemas.definition.ts b/packages/imperative/src/imperative/src/config/cmd/update-schemas/update-schemas.definition.ts index 5808dfe9bd..572dbcd711 100644 --- a/packages/imperative/src/imperative/src/config/cmd/update-schemas/update-schemas.definition.ts +++ b/packages/imperative/src/imperative/src/config/cmd/update-schemas/update-schemas.definition.ts @@ -16,7 +16,7 @@ export const updateSchemasDefinition: ICommandDefinition = { name: "update-schemas", aliases: ["us"], type: "command", - summary: "update schema files", + summary: "Update schema files", description: "Update schema files by looking up the directory structure.\n\n" + "Schema files up in higher level directories will always be updated. " + "To also update schema files down in lower level directories, specify the `--depth` flag.", diff --git a/packages/imperative/src/imperative/src/doc/IImperativeConfig.ts b/packages/imperative/src/imperative/src/doc/IImperativeConfig.ts index 2142fe3c5a..473941bae8 100644 --- a/packages/imperative/src/imperative/src/doc/IImperativeConfig.ts +++ b/packages/imperative/src/imperative/src/doc/IImperativeConfig.ts @@ -233,31 +233,6 @@ export interface IImperativeConfig { */ pluginLifeCycle?: string; - /** - * A path to a module (javascript file) that will perform a health check for a plugin. - * The health check should verify the health of the plugin. - * The implementor of a plugin determines what actions - * can confirm that the plugin is in an operational state. - * - * The health check should return true if all plugin health checks pass. - * It should return false otherwise. - * - * This property is unused for a base CLI. - * - * No Zowe CLI command currently calls the health check function. - * - * @deprecated - * This property is deprecated. Plugins that want to perform a health check can - * specify the pluginLifeCycle property to load a class from the plugin. - * The plugin can implement the postInstall() function of that class to perform - * a health check, or any other desired operation. Our intention is to remove - * the pluginHealthCheck property in Zowe V3. - * - * @type {string} - * @memberof IImperativeConfig - */ - pluginHealthCheck?: string; - /** * If the project you are configuring is an Imperative plugin, * you can assign aliases to the group that is added when a user diff --git a/packages/imperative/src/imperative/src/doc/IImperativeVersions.ts b/packages/imperative/src/imperative/src/doc/IImperativeVersions.ts new file mode 100644 index 0000000000..eeee41de35 --- /dev/null +++ b/packages/imperative/src/imperative/src/doc/IImperativeVersions.ts @@ -0,0 +1,25 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +export interface IImperativeVersions { + /** + * The version of the consuming program, retrieved from `version` in package.json + * @type {string} + * @memberof IImperativeVersions + */ + version: string, + /** + * The Zowe LTS release number from the consuming program, retrieved from `zoweVersion` in package.json + * @type {string} + * @memberof IImperativeVersions + */ + zoweVersion?: string +} \ No newline at end of file diff --git a/packages/imperative/src/imperative/src/handlers/DefaultRootCommandHandler.ts b/packages/imperative/src/imperative/src/handlers/DefaultRootCommandHandler.ts index 176b8b7775..3232c829cb 100644 --- a/packages/imperative/src/imperative/src/handlers/DefaultRootCommandHandler.ts +++ b/packages/imperative/src/imperative/src/handlers/DefaultRootCommandHandler.ts @@ -10,9 +10,12 @@ */ import { Imperative } from "../../../imperative/src/Imperative"; -import { ICommandHandler, IHandlerParameters, ICommandTreeEntry, CommandUtils } from "../../../cmd"; +import { ICommandTreeEntry } from "../../../cmd/src/utils/CommandUtils"; +import { CommandUtils } from "../../../cmd/src/utils/CommandUtils"; +import { ICommandHandler, IHandlerParameters } from "../../../cmd"; import { ImperativeConfig, TextUtils } from "../../../utilities"; import { WebHelpManager } from "../../../cmd/src/help/WebHelpManager"; +import { IImperativeVersions } from "../doc/IImperativeVersions"; /** * The default command handler for the top level/root command * Allows the user to check the version of the package. @@ -24,9 +27,14 @@ export default class DefaultRootCommandHandler implements ICommandHandler { if (params.arguments.version) { // load the user's package.json to check the version of their package const packageJson: any = ImperativeConfig.instance.callerPackageJson; - params.response.console.log(packageJson.version); - params.response.data.setObj({ version: packageJson.version }); - params.response.data.setMessage("Version displayed"); + const jsonResponse: IImperativeVersions = { version: packageJson.version }; + params.response.console.log("CLI Version: " + packageJson.version); + if (packageJson.zoweVersion) { + params.response.console.log("Zowe Release Version: " + packageJson.zoweVersion); + jsonResponse.zoweVersion = packageJson.zoweVersion; + } + params.response.data.setObj(jsonResponse); + params.response.data.setMessage("Version(s) displayed"); } else if(params.arguments.availableCommands) { // Gather and display the full set of commands available to the CLI with descriptions diff --git a/packages/imperative/src/imperative/src/help/ImperativeHelpGeneratorFactory.ts b/packages/imperative/src/imperative/src/help/ImperativeHelpGeneratorFactory.ts index 3b3d585f30..605a7181b5 100644 --- a/packages/imperative/src/imperative/src/help/ImperativeHelpGeneratorFactory.ts +++ b/packages/imperative/src/imperative/src/help/ImperativeHelpGeneratorFactory.ts @@ -9,10 +9,10 @@ * */ -import { IHelpGenerator, - HelpGeneratorFactory, - IHelpGeneratorParms, - AbstractHelpGeneratorFactory } from "../../../cmd"; +import { IHelpGenerator } from "../../../cmd/src/help/doc/IHelpGenerator"; +import { HelpGeneratorFactory } from "../../../cmd/src/help/HelpGeneratorFactory"; +import { IHelpGeneratorParms } from "../../../cmd/src/help/doc/IHelpGeneratorParms"; +import { AbstractHelpGeneratorFactory } from "../../../cmd/src/help/abstract/AbstractHelpGeneratorFactory"; import { IImperativeConfig } from "../doc/IImperativeConfig"; /** * Imperative Help generator factory passed to yargs to build help generators where needed. diff --git a/packages/imperative/src/imperative/src/plugins/PluginManagementFacility.ts b/packages/imperative/src/imperative/src/plugins/PluginManagementFacility.ts index dda75c20d4..58094e46a5 100644 --- a/packages/imperative/src/imperative/src/plugins/PluginManagementFacility.ts +++ b/packages/imperative/src/imperative/src/plugins/PluginManagementFacility.ts @@ -121,7 +121,7 @@ export class PluginManagementFacility { private pluginIssues = PluginIssues.instance; /** - * A set of bright dependencies used by plugins. Each item in the + * A set of Zowe dependencies used by plugins. Each item in the * set contains the dependency's property name, and the the version * of that dependency. * @@ -166,6 +166,7 @@ export class PluginManagementFacility { UpdateImpConfig.addCmdGrp({ name: "plugins", type: "group", + summary: "Install and manage plug-ins", description: "Install and manage plug-ins.", children: [ // Done dynamically so that PMFConstants can be initialized @@ -224,7 +225,6 @@ export class PluginManagementFacility { */ public loadAllPluginCfgProps(): void { // Initialize the plugin.json file if needed - // TODO Skip creation of PMF_ROOT directory once it is deprecated by team config if (!existsSync(this.pmfConst.PLUGIN_JSON)) { if (!existsSync(this.pmfConst.PMF_ROOT)) { this.impLogger.debug("Creating PMF_ROOT directory"); @@ -280,7 +280,7 @@ export class PluginManagementFacility { * We must find the plugin name from within our known credMgr overrides. */ const credMgrInfo = CredentialManagerOverride.getCredMgrInfoByDisplayName(overrideDispNm); - if ( credMgrInfo === null) { + if (credMgrInfo === null) { credMgrIsUnknown = true; } else { // record the known plugin name that we found for this display name @@ -520,42 +520,36 @@ export class PluginManagementFacility { * Compare the version of a plugin version property with a version property * of its base CLI. * - * If the versions do not intersect (according so semver rules), then a - * PluginIssue is recorded. + * If the versions do not satisfy the semver rules, then a PluginIssue is recorded. * * @param pluginName - The name of the plugin. - * * @param pluginVerPropNm - The name of the plugin property containing a version. - * - * @param pluginVerVal - value of the plugin's version. - * + * @param pluginVerRange - value of the plugin's version. * @param cliVerPropNm - The name of the base CLI property containing a version. - * - * @param cliVerVal - value of the base CLI's version. - * + * @param cliVerValue - value of the base CLI's version. */ private comparePluginVersionToCli( pluginName: string, pluginVerPropNm: string, - pluginVerVal: string, + pluginVerRange: string, cliVerPropNm: string, - cliVerVal: string + cliVerValue: string ): void { const cliCmdName = ImperativeConfig.instance.rootCommandName; try { - if (!this.semver.intersects(cliVerVal, pluginVerVal, false)) { + if (!this.semver.satisfies(cliVerValue, pluginVerRange)) { this.pluginIssues.recordIssue(pluginName, IssueSeverity.WARNING, - "The version value (" + pluginVerVal + ") of the plugin's '" + + "The version value (" + pluginVerRange + ") of the plugin's '" + pluginVerPropNm + "' property is incompatible with the version value (" + - cliVerVal + ") of the " + cliCmdName + " command's '" + + cliVerValue + ") of the " + cliCmdName + " command's '" + cliVerPropNm + "' property." ); } } catch (semverExcept) { PluginIssues.instance.recordIssue(pluginName, IssueSeverity.WARNING, "Failed to compare the version value (" + - pluginVerVal + ") of the plugin's '" + pluginVerPropNm + - "' property with the version value (" + cliVerVal + + pluginVerRange + ") of the plugin's '" + pluginVerPropNm + + "' property with the version value (" + cliVerValue + ") of the " + cliCmdName + " command's '" + cliVerPropNm + "' property.\n" + "This can occur when one of the specified values is not a valid version string.\n" + "Reported reason = " + semverExcept.message @@ -630,9 +624,8 @@ export class PluginManagementFacility { */ if (pluginGroupNm.toLowerCase() === cmdTreeDef.name.toLowerCase()) { const conflictMessage = this.impLogger.error("The plugin named '%s' attempted to add a group of commands" + - " with the name '%s'" + - ". Your base application already contains a group with the name '%s'.", pluginGroupNm, pluginGroupDefinition.name, - cmdTreeDef.name); + " with the name '%s'. Your base application already contains a group with the name '%s'.", + pluginGroupNm, pluginGroupDefinition.name, cmdTreeDef.name); return { hasConflict: true, message: conflictMessage }; } @@ -640,9 +633,8 @@ export class PluginManagementFacility { for (const pluginAlias of pluginGroupDefinition.aliases) { if (pluginAlias.toLowerCase() === cmdTreeDef.name.toLowerCase()) { const conflictMessage = this.impLogger.error("The plugin named '%s' attempted to add a group of commands" + - " with the alias '%s' " + - ". Your base application already contains a group with the name '%s'.", pluginGroupNm, pluginAlias, - cmdTreeDef.name); + " with the alias '%s' . Your base application already contains a group with the name '%s'.", + pluginGroupNm, pluginAlias, cmdTreeDef.name); return { hasConflict: true, message: conflictMessage }; } } @@ -655,8 +647,8 @@ export class PluginManagementFacility { // if the plugin name matches an alias of the definition tree if (pluginGroupNm.toLowerCase() === nextAliasToTest.toLowerCase()) { const conflictMessage = this.impLogger.error("The plugin attempted to add a group of commands with the name '%s' " + - ". Your base application already contains a group with an alias '%s'.", pluginGroupNm, nextAliasToTest, - cmdTreeDef.name); + ". Your base application already contains a group with an alias '%s'.", + pluginGroupNm, nextAliasToTest, cmdTreeDef.name); return { hasConflict: true, message: conflictMessage }; } if (pluginGroupDefinition.aliases != null) { @@ -664,9 +656,8 @@ export class PluginManagementFacility { // if an alias of the plugin matches an alias of hte definition tree if (pluginAlias.toLowerCase() === nextAliasToTest.toLowerCase()) { const conflictMessage = this.impLogger.error("The plugin named '%s' attempted to add a " + - "group of command with the alias '%s', which conflicts with " + - "another alias of the same name for group '%s'.", pluginGroupDefinition.name, pluginAlias, - cmdTreeDef.name); + "group of command with the alias '%s', which conflicts with another alias of the same name for group '%s'.", + pluginGroupDefinition.name, pluginAlias, cmdTreeDef.name); return { hasConflict: true, message: conflictMessage }; } } @@ -888,19 +879,17 @@ export class PluginManagementFacility { */ const knownCredMgrs: ICredentialManagerNameMap[] = CredentialManagerOverride.getKnownCredMgrs(); overrideErrMsg += `"${settingNm}": "${CredentialManagerOverride.DEFAULT_CRED_MGR_NAME}" (default)`; - for ( let credMgrInx = 1; credMgrInx < knownCredMgrs.length; credMgrInx++) { + for (let credMgrInx = 1; credMgrInx < knownCredMgrs.length; credMgrInx++) { overrideErrMsg += `\n"${settingNm}": "${knownCredMgrs[credMgrInx].credMgrDisplayName}" `; - if ( typeof(knownCredMgrs[credMgrInx].credMgrPluginName) !== "undefined") { + if (typeof knownCredMgrs[credMgrInx].credMgrPluginName !== "undefined") { overrideErrMsg += `(supplied in CLI plugin ${knownCredMgrs[credMgrInx].credMgrPluginName}`; } - if ( typeof(knownCredMgrs[credMgrInx].credMgrZEName) !== "undefined") { + if (typeof knownCredMgrs[credMgrInx].credMgrZEName !== "undefined") { const punctuation = 8; overrideErrMsg += "\n"; - for (let indent: number = 0; indent < - settingNm.length + knownCredMgrs[credMgrInx].credMgrDisplayName.length + punctuation; - indent++ ) - { + const indentLength = settingNm.length + `${knownCredMgrs[credMgrInx].credMgrDisplayName}`.length + punctuation; + for (let indent: number = 0; indent < indentLength; indent++) { overrideErrMsg += " "; } overrideErrMsg += `and in ZE extension ${knownCredMgrs[credMgrInx].credMgrZEName}`; @@ -936,8 +925,8 @@ export class PluginManagementFacility { * with those specified in the host CLI. * * Both range strings come from the package.json files of the plugin and the - * hosting CLI. We consider the version ranges to be compatible if the two - * ranges intersect. This should allow npm to download one common version + * hosting CLI. We consider the version ranges to be compatible if they satisfy + * the CLI version range. This should allow npm to download one common version * of core and of imperative to be owned by the base CLI and shared by the plugin. * * Any errors are recorded in PluginIssues. diff --git a/packages/imperative/src/imperative/src/plugins/PluginRequireProvider.ts b/packages/imperative/src/imperative/src/plugins/PluginRequireProvider.ts index 2b756ccd32..b7896a3660 100644 --- a/packages/imperative/src/imperative/src/plugins/PluginRequireProvider.ts +++ b/packages/imperative/src/imperative/src/plugins/PluginRequireProvider.ts @@ -32,7 +32,7 @@ import * as lodash from "lodash"; * PluginRequireProvider.createPluginHooks(["module-a", "module-b"]); * * // Now in all places of the application, module-a and module-b will be loaded - * // from the package location of process.mainModule (I.E the Host Package). This + * // from the package location of require.main (I.E the Host Package). This * // is useful when the Host Package has some sort of plugin infrastructure that * // might require modules to be injected to the plugins. * @@ -160,6 +160,7 @@ export class PluginRequireProvider { */ const regex = this.regex = new RegExp(`^(${internalModules.join("|")})(?:\\/.*)?$`, "gm"); const origRequire = this.origRequire = Module.prototype.require; + const origMain = this.origRequire.main; // Timerify the function if needed // Gave it a name so that we can more easily track it @@ -180,8 +181,7 @@ export class PluginRequireProvider { } // Inject it from the main module dependencies - // eslint-disable-next-line deprecation/deprecation - return origRequire.apply(process.mainModule, args); + return origRequire.apply(origMain, args); } else { // Otherwise use the package dependencies return origRequire.apply(this, args); diff --git a/packages/imperative/src/imperative/src/plugins/cmd/install/install.handler.ts b/packages/imperative/src/imperative/src/plugins/cmd/install/install.handler.ts index c7d43271b1..9f36fa32c7 100644 --- a/packages/imperative/src/imperative/src/plugins/cmd/install/install.handler.ts +++ b/packages/imperative/src/imperative/src/plugins/cmd/install/install.handler.ts @@ -20,14 +20,17 @@ import { readFileSync } from "jsonfile"; import { ImperativeConfig, TextUtils } from "../../../../../utilities"; import { ImperativeError } from "../../../../../error"; import { runValidatePlugin } from "../../utilities/runValidatePlugin"; -import { getRegistry, npmLogin } from "../../utilities/NpmFunctions"; - +import { + getRegistry, + getScopeRegistry, + npmLogin, +} from "../../utilities/NpmFunctions"; +import { IO } from "../../../../../io"; /** * The install command handler for cli plugin install. * * @see {installDefinition} - */ -export default class InstallHandler implements ICommandHandler { + */ export default class InstallHandler implements ICommandHandler { /** * A logger for this class * @@ -69,114 +72,206 @@ export default class InstallHandler implements ICommandHandler { * * @throws {ImperativeError} */ + + private locationTypeTest(plugin: string){ + let isDirTest: boolean; + let installRegistry = getRegistry(); + try { + isDirTest = IO.isDir(plugin); + } catch (e) { + isDirTest = false; + } + + if (plugin.startsWith("@")) { + installRegistry = getScopeRegistry( + plugin.split("/")[0].substring(1) + ).replace("\n", ""); + } else if ( + plugin.substring(plugin.lastIndexOf(".") + 1) === "tgz" || + isDirTest + ) { + installRegistry = plugin; + } + return installRegistry; + } + public async process(params: IHandlerParameters): Promise { const chalk = TextUtils.chalk; - this.console.debug(`Root Directory: ${PMFConstants.instance.PLUGIN_INSTALL_LOCATION}`); + this.console.debug( + `Root Directory: ${PMFConstants.instance.PLUGIN_INSTALL_LOCATION}` + ); - if (params.arguments.plugin != null && params.arguments.plugin.length > 0 && typeof params.arguments.file !== "undefined") { + if ( + params.arguments.plugin != null && + params.arguments.plugin.length > 0 && + typeof params.arguments.file !== "undefined" + ) { throw new ImperativeError({ - msg: `Option ${chalk.yellow.bold("--file")} can not be specified if positional ${chalk.yellow.bold("package...")} is as well. ` + - `They are mutually exclusive.` + msg: + `Option ${chalk.yellow.bold( + "--file" + )} can not be specified if positional ${chalk.yellow.bold( + "package..." + )} is as well. ` + `They are mutually exclusive.`, }); } else { try { - let installRegistry: any; - - // Get the registry to install to - if (typeof params.arguments.registry === "undefined") { - installRegistry = getRegistry().replace("\n", ""); - } else { - installRegistry = params.arguments.registry; - if (params.arguments.login) { - npmLogin(installRegistry); - } - } - - params.response.console.log( - "Plug-ins within the Imperative CLI Framework can legitimately gain\n" + - `control of the ${ImperativeConfig.instance.rootCommandName} CLI application ` + - "during the execution of every command.\n" + - "Install 3rd party plug-ins at your own risk.\n" - ); - - params.response.console.log("Registry = " + installRegistry); + let installRegistry = + params.arguments.registry ?? + getRegistry().replace("\n", ""); // This section determines which npm logic needs to take place - if (params.arguments.plugin == null || params.arguments.plugin.length === 0) { - const configFile = typeof params.arguments.file === "undefined" ? - PMFConstants.instance.PLUGIN_JSON : - resolve(params.arguments.file); + if ( + params.arguments.plugin == null || + params.arguments.plugin.length === 0 + ) { + const configFile = + typeof params.arguments.file === "undefined" + ? PMFConstants.instance.PLUGIN_JSON + : resolve(params.arguments.file); - this.console.debug("Need to install using plugins.json file"); + this.console.debug( + "Need to install using plugins.json file" + ); this.console.debug(`Using config file: ${configFile}`); // Attempt to load that file and formulate the corresponding package const packageJson: IPluginJson = readFileSync(configFile); if (Object.keys(packageJson).length === 0) { - params.response.console.log("No packages were found in " + - configFile + ", so no plugins were installed."); + params.response.console.log( + "No packages were found in " + + configFile + + ", so no plugins were installed." + ); return; } for (const packageName in packageJson) { - if (Object.prototype.hasOwnProperty.call(packageJson, packageName)) { - const packageInfo: IPluginJsonObject = packageJson[packageName]; + if ( + Object.prototype.hasOwnProperty.call( + packageJson, + packageName + ) + ) { + const packageInfo: IPluginJsonObject = + packageJson[packageName]; // Registry is typed as optional in the doc but the function expects it // to be passed. So we'll always set it if it hasn't been done yet. - if (!packageInfo.registry) { - packageInfo.registry = installRegistry; + if (!packageInfo.location) { + packageInfo.location = installRegistry; } - this.console.debug(`Installing plugin: ${packageName}`); - this.console.debug(`Location: ${packageInfo.package}`); - this.console.debug(`Registry: ${packageInfo.registry}`); - this.console.debug(`Version : ${packageInfo.version}`); + installRegistry = this.locationTypeTest(packageInfo.location); + + this.console.debug( + `Installing plugin: ${packageName}` + ); + this.console.debug( + `Package: ${packageInfo.package}` + ); + this.console.debug( + `Location: ${packageInfo.location}` + ); + this.console.debug( + `Version : ${packageInfo.version}` + ); // Get the argument to the install command // For simplicity a / or \ indicates that we are not dealing with an npm package - const packageArgument = packageInfo.package === packageName ? - `${packageInfo.package}@${packageInfo.version}` : - packageInfo.package; + const packageArgument = + packageInfo.package === packageName + ? `${packageInfo.package}@${packageInfo.version}` + : packageInfo.package; this.console.debug(`Package: ${packageArgument}`); - params.response.console.log("\n_______________________________________________________________"); - const pluginName = await install(packageArgument, packageInfo.registry, true); - params.response.console.log("Installed plugin name = '" + pluginName + "'"); - params.response.console.log(runValidatePlugin(pluginName)); + params.response.console.log( + "Plug-ins within the Imperative CLI Framework can legitimately gain\n" + + `control of the ${ImperativeConfig.instance.rootCommandName} CLI application ` + + "during the execution of every command.\n" + + "Install 3rd party plug-ins at your own risk.\n" + ); + params.response.console.log( + "Location = " + installRegistry + ); + + params.response.console.log( + "\n_______________________________________________________________" + ); + const pluginName = await install( + packageArgument, + packageInfo.location, + true + ); + params.response.console.log( + "Installed plugin name = '" + pluginName + "'" + ); + params.response.console.log( + runValidatePlugin(pluginName) + ); } } + } - // write the json file when done if not the plugin json file - } else { - for (const packageString of params.arguments.plugin) { - params.response.console.log("\n_______________________________________________________________"); - const pluginName = await install(`${packageString}`, installRegistry); - params.response.console.log("Installed plugin name = '" + pluginName + "'"); - params.response.console.log(runValidatePlugin(pluginName)); + for (const plugin of params.arguments.plugin ?? []) { + // Get the registry to install to + if (typeof params.arguments.registry === "undefined") { + installRegistry = this.locationTypeTest(plugin); + } else { + installRegistry = params.arguments.registry; + if (params.arguments.login) { + npmLogin(installRegistry); + } } + params.response.console.log( + "Plug-ins within the Imperative CLI Framework can legitimately gain\n" + + `control of the ${ImperativeConfig.instance.rootCommandName} CLI application ` + + "during the execution of every command.\n" + + "Install 3rd party plug-ins at your own risk.\n" + ); + params.response.console.log( + "Location = " + installRegistry + ); + + params.response.console.log( + "\n_______________________________________________________________" + ); + const pluginName = await install( + `${plugin}`, + installRegistry + ); + params.response.console.log( + "Installed plugin name = '" + pluginName + "'" + ); + params.response.console.log(runValidatePlugin(pluginName)); } } catch (e) { let installResultMsg = "Install Failed"; /* When we fail to create symbolic links to core and imperative, - * give a special message, as per UX request. - */ + * give a special message, as per UX request. + */ if (e.mMessage) { - const matchArray = e.mMessage.match(/The intended symlink.*already exists and is not a symbolic link/); + const matchArray = e.mMessage.match( + /The intended symlink.*already exists and is not a symbolic link/ + ); if (matchArray !== null) { - installResultMsg = "Installation completed. However, the plugin incorrectly contains\nits own copy of " + + installResultMsg = + "Installation completed. However, the plugin incorrectly contains\nits own copy of " + `${PMFConstants.instance.CLI_CORE_PKG_NAME} or ${PMFConstants.instance.IMPERATIVE_PKG_NAME}.\n` + "Some plugin operations may not work correctly."; - } else if (e.mMessage.includes("Failed to create symbolic link")) { - installResultMsg = "Installation completed. However, due to the following error, the plugin will not operate correctly."; + } else if ( + e.mMessage.includes("Failed to create symbolic link") + ) { + installResultMsg = + "Installation completed. However, due to the following error, the plugin will not operate correctly."; } } throw new ImperativeError({ msg: installResultMsg, causeErrors: e, - additionalDetails: e.message + additionalDetails: e.message, }); } } diff --git a/packages/imperative/src/imperative/src/plugins/cmd/list/list.handler.ts b/packages/imperative/src/imperative/src/plugins/cmd/list/list.handler.ts index 0ceb5b8499..176d72db34 100644 --- a/packages/imperative/src/imperative/src/plugins/cmd/list/list.handler.ts +++ b/packages/imperative/src/imperative/src/plugins/cmd/list/list.handler.ts @@ -47,6 +47,9 @@ export default class ListHandler implements ICommandHandler { let listOutput: string = ""; let firstTime = true; + // Boolean to check if any of the plug-ins installed originate from Zowe Cli V2 + let containsLegacyPlugin: boolean = false; + for (const pluginName of Object.keys(installedPlugins).sort((a, b) => a.localeCompare(b))) { if (Object.prototype.hasOwnProperty.call(installedPlugins, pluginName)) { // Build the console output @@ -61,8 +64,19 @@ export default class ListHandler implements ICommandHandler { `${chalk.red.bold(installedPlugins[pluginName].package)} \n`; listOutput = listOutput + `${chalk.yellow.bold(" -- version: ")}` + `${chalk.red.bold(installedPlugins[pluginName].version)} \n`; - listOutput = listOutput + `${chalk.yellow.bold(" -- registry: ")}` + - installedPlugins[pluginName].registry + "\n\n"; + + if((installedPlugins[pluginName] as any).registry) + { + containsLegacyPlugin = true; + listOutput = listOutput + `${chalk.yellow.bold(" -- registry: ")}` + + `${chalk.red.bold((installedPlugins[pluginName] as any).registry)}` + + `${chalk.yellow.bold(" (?)")}` + "\n\n"; + } + else + { + listOutput = listOutput + `${chalk.yellow.bold(" -- location: ")}` + + `${chalk.red.bold(installedPlugins[pluginName].location)}` + "\n\n"; + } } else { listOutput += `${chalk.yellow(pluginName)}@${installedPlugins[pluginName].version}\n`; } @@ -77,11 +91,16 @@ export default class ListHandler implements ICommandHandler { this.log.simple(" pluginName: " + pluginName); this.log.simple(" package: " + installedPlugins[pluginName].package); this.log.simple(" version: " + installedPlugins[pluginName].version); - this.log.simple(" registry: " + installedPlugins[pluginName].registry); + this.log.simple(" registry: " + installedPlugins[pluginName].location); this.log.simple(" "); } } + if(containsLegacyPlugin) + { + listOutput += chalk.yellow.bold("Plug-ins marked with (?) may be invalid or out of date, and might need to be reinstalled.") + "\n"; + } + if (listOutput === "") { listOutput = "No plugins have been installed into your CLI application."; } diff --git a/packages/imperative/src/imperative/src/plugins/cmd/showfirststeps/showfirststeps.definition.ts b/packages/imperative/src/imperative/src/plugins/cmd/showfirststeps/showfirststeps.definition.ts index ff53c7e794..34893a117c 100644 --- a/packages/imperative/src/imperative/src/plugins/cmd/showfirststeps/showfirststeps.definition.ts +++ b/packages/imperative/src/imperative/src/plugins/cmd/showfirststeps/showfirststeps.definition.ts @@ -24,8 +24,8 @@ export const firststepsDefinition: ICommandDefinition = { name: "show-first-steps", type: "command", aliases: ["fs"], - summary: "Show first steps for a plugin", - description: "Show first steps required to set up plugin for use.", + summary: "Show first steps for a plug-in", + description: "Show first steps required to set up plug-in for use.", handler: join(__dirname, "showfirststeps.handler"), positionals: [ { @@ -39,7 +39,7 @@ export const firststepsDefinition: ICommandDefinition = { // ], examples: [ { - description: `Show first steps for a plugin called 'my-plugin'`, + description: `Show first steps for a plug-in called 'my-plugin'`, options: "my-plugin" } ] diff --git a/packages/imperative/src/imperative/src/plugins/cmd/update/update.handler.ts b/packages/imperative/src/imperative/src/plugins/cmd/update/update.handler.ts index c4ddecf3f9..551af090b4 100644 --- a/packages/imperative/src/imperative/src/plugins/cmd/update/update.handler.ts +++ b/packages/imperative/src/imperative/src/plugins/cmd/update/update.handler.ts @@ -77,11 +77,11 @@ export default class UpdateHandler implements ICommandHandler { // folder location. Example: plugin 'imperative-sample-plugin' installed from ../imperative-plugins packageName = installedPlugins[pluginName].package; if (registry === undefined) { - registry = installedPlugins[pluginName].registry; + registry = installedPlugins[pluginName].location; } // Call update which returns the plugin's version so plugins.json can be updated installedPlugins[pluginName].version = await update(packageName, registry); - installedPlugins[pluginName].registry = registry; // update in case it changed + installedPlugins[pluginName].location = registry; // update in case it changed writeFileSync(PMFConstants.instance.PLUGIN_JSON, installedPlugins, { spaces: 2 diff --git a/packages/imperative/src/imperative/src/plugins/cmd/validate/validate.definition.ts b/packages/imperative/src/imperative/src/plugins/cmd/validate/validate.definition.ts index 43e9365004..57947d1915 100644 --- a/packages/imperative/src/imperative/src/plugins/cmd/validate/validate.definition.ts +++ b/packages/imperative/src/imperative/src/plugins/cmd/validate/validate.definition.ts @@ -40,7 +40,7 @@ export const validateDefinition: ICommandDefinition = { name: "fail-on-error", aliases: ["foe"], type: "boolean", - description: "Enables throwing an error and setting an error code if plugin validation detects an error", + description: "Enables throwing an error and setting an error code if plugin validation detects an error.", required: false, defaultValue: true }, diff --git a/packages/imperative/src/imperative/src/plugins/doc/IPluginJsonObject.ts b/packages/imperative/src/imperative/src/plugins/doc/IPluginJsonObject.ts index 91b6f59606..acf6296cd2 100644 --- a/packages/imperative/src/imperative/src/plugins/doc/IPluginJsonObject.ts +++ b/packages/imperative/src/imperative/src/plugins/doc/IPluginJsonObject.ts @@ -23,11 +23,11 @@ export interface IPluginJsonObject { package: string; /** - * The npm registry to install from. + * The npm location to install from. * * @type {string} */ - registry: string; + location: string; /** * The version of the installed plugin. diff --git a/packages/imperative/src/imperative/src/plugins/utilities/NpmFunctions.ts b/packages/imperative/src/imperative/src/plugins/utilities/NpmFunctions.ts index 52e0f12ea2..0acb75ac1a 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/NpmFunctions.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/NpmFunctions.ts @@ -17,6 +17,7 @@ import { readFileSync } from "jsonfile"; import * as npmPackageArg from "npm-package-arg"; import * as pacote from "pacote"; import { ExecUtils } from "../../../../utilities"; +import { IO } from "../../../../io"; const npmCmd = findNpmOnPath(); /** @@ -41,21 +42,36 @@ export function findNpmOnPath(): string { */ export function installPackages(prefix: string, registry: string, npmPackage: string): string { const pipe: StdioOptions = ["pipe", "pipe", process.stderr]; - const execOutput = ExecUtils.spawnAndGetOutput(npmCmd, - [ - "install", npmPackage, - "--prefix", prefix, - "-g", - "--registry", registry, - "--legacy-peer-deps" - ], { - cwd: PMFConstants.instance.PMF_ROOT, - stdio: pipe - } - ); + + const args = [ + "install", npmPackage, + "--prefix", prefix, + "-g" + ]; + let isDirTest: boolean; + + try{ + isDirTest = IO.isDir(registry); + } + catch(e){ + isDirTest = false; + } + + if (!(registry.substring(registry.lastIndexOf(".") + 1) === "tgz") && !isDirTest) { + args.push("--registry",registry); + } + + args.push("--legacy-peer-deps"); + + const execOutput = ExecUtils.spawnAndGetOutput(npmCmd, args, { + cwd: PMFConstants.instance.PMF_ROOT, + stdio: pipe + }); + return execOutput.toString(); } + /** * Get the registry to install to. * @@ -66,6 +82,12 @@ export function getRegistry(): string { return execOutput.toString(); } +export function getScopeRegistry(scope: string): string { + const execOutput = ExecUtils.spawnAndGetOutput(npmCmd, [ "config", "get", `@${scope}:registry` ]); + if(execOutput.toString().trim() === 'undefined') return getRegistry(); + return execOutput.toString(); +} + /** * NPM login to be able to install from secure registry * @param {string} registry The npm registry to install from. diff --git a/packages/imperative/src/imperative/src/plugins/utilities/PMFConstants.ts b/packages/imperative/src/imperative/src/plugins/utilities/PMFConstants.ts index b411a59763..c1b2ef84a0 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/PMFConstants.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/PMFConstants.ts @@ -139,7 +139,7 @@ export class PMFConstants { if (this.PLUGIN_USING_CONFIG) { this.PLUGIN_CONFIG.paths.forEach((path: string) => { const dir = dirname(path); - modPaths.push(join(dir, (process.platform !== "win32") ? "lib" : "", "node_modules")); + modPaths.push(join(dir, process.platform !== "win32" ? "lib" : "", "node_modules")); }); } modPaths.push(this.PLUGIN_HOME_LOCATION); diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts index 40f6e95a0e..ea6d4030fd 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/install.ts @@ -26,7 +26,7 @@ import { UpdateImpConfig } from "../../../UpdateImpConfig"; import { CredentialManagerOverride, ICredentialManagerNameMap } from "../../../../../security"; import { IProfileTypeConfiguration } from "../../../../../profiles"; import * as semver from "semver"; -import { ProfileInfo } from "../../../../../config"; +import { ConfigUtils } from "../../../../../config"; import { IExtendersJsonOpts } from "../../../../../config/src/doc/IExtenderOpts"; // Helper function to update extenders.json object during plugin install. @@ -150,7 +150,7 @@ export async function install(packageLocation: string, registry: string, install const newPlugin: IPluginJsonObject = { package: npmPackage, - registry, + location: registry, version: packageVersion }; iConsole.debug("Updating the current configuration with new plugin:\n" + @@ -167,7 +167,7 @@ export async function install(packageLocation: string, registry: string, install const requirerFunction = PluginManagementFacility.instance.requirePluginModuleCallback(packageName); const pluginImpConfig = ConfigurationLoader.load(null, packageInfo, requirerFunction); - iConsole.debug(`Checking for global team configuration files to update.`); + iConsole.debug(`Checking for global Zowe client configuration files to update.`); if (PMFConstants.instance.PLUGIN_USING_CONFIG) { // Update the Imperative Configuration to add the profiles introduced by the recently installed plugin @@ -188,7 +188,7 @@ export async function install(packageLocation: string, registry: string, install // Only update global schema if we were able to load it from disk if (loadedSchema != null) { const existingTypes = loadedSchema.map((obj) => obj.type); - const extendersJson = ProfileInfo.readExtendersJsonFromDisk(); + const extendersJson = ConfigUtils.readExtendersJson(); // Determine new profile types to add to schema let shouldUpdate = false; @@ -212,7 +212,7 @@ export async function install(packageLocation: string, registry: string, install if (shouldUpdate) { // Update extenders.json (if necessary) after installing the plugin - ProfileInfo.writeExtendersJson(extendersJson); + ConfigUtils.writeExtendersJson(extendersJson); } const schema = ConfigSchema.buildSchema(loadedSchema); ConfigSchema.updateSchema({ layer: "global", schema }); diff --git a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts index c03909a690..90e001720d 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/npm-interface/uninstall.ts @@ -19,8 +19,9 @@ import { ImperativeError } from "../../../../../error"; import { ExecUtils, TextUtils } from "../../../../../utilities"; import { StdioOptions } from "child_process"; import { findNpmOnPath } from "../NpmFunctions"; -import { ConfigSchema, ProfileInfo } from "../../../../../config"; +import { ConfigSchema, ConfigUtils } from "../../../../../config"; import { IProfileTypeConfiguration } from "../../../../../profiles"; + const npmCmd = findNpmOnPath(); /** @@ -29,7 +30,7 @@ const npmCmd = findNpmOnPath(); * @returns A list of types to remove from the schema */ export const updateAndGetRemovedTypes = (npmPackage: string): string[] => { - const extendersJson = ProfileInfo.readExtendersJsonFromDisk(); + const extendersJson = ConfigUtils.readExtendersJson(); const pluginTypes = Object.keys(extendersJson.profileTypes) .filter((type) => extendersJson.profileTypes[type].from.includes(npmPackage)); const typesToRemove: string[] = []; @@ -58,7 +59,7 @@ export const updateAndGetRemovedTypes = (npmPackage: string): string[] => { typesToRemove.push(profileType); } } - ProfileInfo.writeExtendersJson(extendersJson); + ConfigUtils.writeExtendersJson(extendersJson); } return typesToRemove; diff --git a/packages/imperative/src/imperative/src/plugins/utilities/runValidatePlugin.ts b/packages/imperative/src/imperative/src/plugins/utilities/runValidatePlugin.ts index c9c408d188..16b73d2072 100644 --- a/packages/imperative/src/imperative/src/plugins/utilities/runValidatePlugin.ts +++ b/packages/imperative/src/imperative/src/plugins/utilities/runValidatePlugin.ts @@ -10,7 +10,7 @@ */ import { Logger } from "../../../../logger"; -import { ExecUtils } from "../../../../utilities"; +import { ExecUtils, ImperativeConfig } from "../../../../utilities"; import { PMFConstants } from "./PMFConstants"; import { ImperativeError } from "../../../../error"; @@ -30,7 +30,7 @@ import { ImperativeError } from "../../../../error"; export function runValidatePlugin(pluginName: string): string { const extLen = 3; const cmdToRun = process.execPath; - const cliPgmToRun = require.main.filename; + const cliPgmToRun = ImperativeConfig.instance.callerLocation ?? require.main.filename; let cmdToRunArgs: string[] = []; if (cliPgmToRun.substring(cliPgmToRun.length - extLen) === ".ts") { cmdToRunArgs = ["--require", "ts-node/register"]; diff --git a/packages/imperative/src/imperative/src/profiles/ImperativeProfileManagerFactory.ts b/packages/imperative/src/imperative/src/profiles/ImperativeProfileManagerFactory.ts deleted file mode 100644 index 8da02adabd..0000000000 --- a/packages/imperative/src/imperative/src/profiles/ImperativeProfileManagerFactory.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { AbstractProfileManagerFactory } from "../../../profiles"; -import { CliProfileManager, ICommandProfileTypeConfiguration } from "../../../cmd/"; -import { ImperativeApi } from "../api/ImperativeApi"; -/** - * The imperative profile manager factory returns instances of the cli profile manager - * @export - * @class ProfileManagerFactory - * @extends {AbstractProfileManagerFactory} - */ -export class ImperativeProfileManagerFactory extends AbstractProfileManagerFactory { - private mImperativeApi: ImperativeApi; - constructor(imperativeApi: ImperativeApi) { - super(); - this.mImperativeApi = imperativeApi; - } - /** - * Returns a instance of the CliProfileManager - * @param {string} type - The profile type you want to manage. - * @returns {CliProfileManager} - The profile manager instance - * @memberof ProfileManagerFactory - */ - public getManager(type: string): CliProfileManager { - return this.mImperativeApi.profileManager(type); - } -} diff --git a/packages/imperative/src/imperative/src/profiles/builders/CompleteProfilesGroupBuilder.ts b/packages/imperative/src/imperative/src/profiles/builders/CompleteProfilesGroupBuilder.ts deleted file mode 100644 index 00cd4f39b5..0000000000 --- a/packages/imperative/src/imperative/src/profiles/builders/CompleteProfilesGroupBuilder.ts +++ /dev/null @@ -1,142 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandDefinition } from "../../../../cmd"; -import { - createProfilesCommandDesc, createProfilesCommandSummary, - deleteProfilesCommandDesc, deleteProfilesCommandSummary, - listProfileCommandDesc, listProfileCommandSummary, - setProfileActionDesc, setProfileActionSummary, - updateProfileCommandDesc, updateProfileCommandSummary, - validateProfileGroupDesc, validateProfileCommandSummary -} from "../../../../messages"; -import { Constants } from "../../../../constants"; -import { ProfilesCreateCommandBuilder } from "./ProfilesCreateCommandBuilder"; -import { ProfilesUpdateCommandBuilder } from "./ProfilesUpdateCommandBuilder"; -import { ProfilesDeleteCommandBuilder } from "./ProfilesDeleteCommandBuilder"; -import { ProfilesValidateCommandBuilder } from "./ProfilesValidateCommandBuilder"; -import { ProfilesListCommandBuilder } from "./ProfilesListCommandBuilder"; -import { ProfilesSetCommandBuilder } from "./ProfilesSetCommandBuilder"; -import { Logger } from "../../../../logger/index"; -import { IProfileTypeConfiguration, ProfilesConstants } from "../../../../profiles"; -import { ImperativeConfig } from "../../../../utilities"; - -/** - * Generate a complete group of commands for maintaining configuration profiles - * based on provided profile definitions. - */ -export class CompleteProfilesGroupBuilder { - - - /** - * Get the complete profile group of commands - * @param {ICommandProfileTypeConfiguration[]} profiles - the profile configurations to convert to commands - * @param {Logger} logger - logger to use in the builder classes - * @returns {ICommandDefinition} - the complete profile group of commands - */ - public static getProfileGroup(profiles: IProfileTypeConfiguration[], logger: Logger): ICommandDefinition { - - const profileGroup: ICommandDefinition = { - name: Constants.PROFILE_GROUP, - description: "Create and manage configuration profiles.", - type: "group", - deprecatedReplacement: ProfilesConstants.DEPRECATE_TO_CONFIG_INIT, - children: [] - }; - - const createGroup: ICommandDefinition = { - name: Constants.CREATE_ACTION, - description: createProfilesCommandDesc.message, - summary: createProfilesCommandSummary.message, - aliases: ["cre"], - type: "group", - deprecatedReplacement: ProfilesConstants.DEPRECATE_TO_CONFIG_INIT, - children: [], - }; - - const deleteGroup: ICommandDefinition = { - name: Constants.DELETE_ACTION, - description: deleteProfilesCommandDesc.message, - summary: deleteProfilesCommandSummary.message, - aliases: ["rm"], - type: "group", - deprecatedReplacement: ProfilesConstants.DEPRECATE_TO_CONFIG_EDIT + " " + - ImperativeConfig.instance.config.formMainConfigPathNm({addPath: false}), - children: [], - }; - - const setGroup: ICommandDefinition = { - name: Constants.SET_ACTION, - summary: setProfileActionSummary.message, - description: setProfileActionDesc.message, - type: "group", - aliases: ["set"], - deprecatedReplacement: ProfilesConstants.DEPRECATE_TO_CONFIG_SET, - children: [], - }; - - const updateGroup: ICommandDefinition = { - name: Constants.UPDATE_ACTION, - description: updateProfileCommandDesc.message, - summary: updateProfileCommandSummary.message, - aliases: ["upd"], - type: "group", - deprecatedReplacement: ProfilesConstants.DEPRECATE_TO_CONFIG_SET, - children: [], - }; - - const validateGroup: ICommandDefinition = { - name: Constants.VALIDATE_ACTION, - description: validateProfileGroupDesc.message, - summary: validateProfileCommandSummary.message, - aliases: ["val"], - type: "group", - deprecatedReplacement: ProfilesConstants.DEPRECATE_TO_CONFIG_EDIT + " " + - ImperativeConfig.instance.config.formMainConfigPathNm({addPath: false}), - children: [], - }; - - const listGroup: ICommandDefinition = { - name: Constants.LIST_ACTION, - description: listProfileCommandDesc.message, - summary: listProfileCommandSummary.message, - aliases: ["ls"], - type: "group", - deprecatedReplacement: ProfilesConstants.DEPRECATE_TO_CONFIG_LIST, - children: [], - }; - - for (const profile of profiles) { - const createCommandAction = new ProfilesCreateCommandBuilder(profile.type, logger, profile); - const updateCommandAction = new ProfilesUpdateCommandBuilder(profile.type, logger, profile); - const deleteCommandAction = new ProfilesDeleteCommandBuilder(profile.type, logger, profile); - const validateCommandAction = new ProfilesValidateCommandBuilder(profile.type, logger, profile); - const listCommandAction = new ProfilesListCommandBuilder(profile.type, logger, profile); - const setCommandAction = new ProfilesSetCommandBuilder(profile.type, logger, profile); - updateGroup.children.push(updateCommandAction.build()); - deleteGroup.children.push(deleteCommandAction.build()); - // validate profile is optional depending on if the profile has a validation plan - const validateCommandResult = validateCommandAction.build(); - if (validateCommandResult != null) { - validateGroup.children.push(validateCommandResult); - } - listGroup.children.push(listCommandAction.build()); - createGroup.children.push(createCommandAction.build()); - setGroup.children.push(setCommandAction.build()); - } - profileGroup.children.push(createGroup, updateGroup, deleteGroup, listGroup, setGroup); - if (validateGroup.children.length > 0) { - // don't bother to add validation commands unless some plans have been provided - profileGroup.children.push(validateGroup); - } - return profileGroup; - } -} diff --git a/packages/imperative/src/imperative/src/profiles/builders/ProfilesCommandBuilder.ts b/packages/imperative/src/imperative/src/profiles/builders/ProfilesCommandBuilder.ts deleted file mode 100644 index 0f2e8ee24e..0000000000 --- a/packages/imperative/src/imperative/src/profiles/builders/ProfilesCommandBuilder.ts +++ /dev/null @@ -1,114 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { AbstractCommandBuilder } from "../../../../cmd/src/builders/AbstractCommandBuilder"; -import { ICommandDefinition, ICommandOptionDefinition, ICommandProfileTypeConfiguration } from "../../../../cmd"; -import { Logger } from "../../../../logger"; -import { IProfileSchema, ProfileUtils } from "../../../../profiles"; -import { ICommandProfileProperty } from "../../../../cmd/src/doc/profiles/definition/ICommandProfileProperty"; - -/** - * Abstract class for generating profile-related commands - */ -export abstract class ProfilesCommandBuilder implements AbstractCommandBuilder { - - /** - * Schema for the command. - */ - protected mSchema: IProfileSchema; - - /** - * Construct the builder based on the schema. - * @param mProfileType - the name of the profile type e.g. banana - * @param {Logger} mLogger - logger instance to use for the builder class - * @param {IProfileSchema} mProfileConfig: The schema that describes the profile - */ - constructor(protected mProfileType: string, - protected mLogger: Logger, - protected mProfileConfig: ICommandProfileTypeConfiguration) { - - this.mSchema = mProfileConfig.schema; - if (this.mSchema == null) { - throw new Error(`Profile Builder Error: No profile schema was supplied.`); - } - } - - /** - * Build the full command - includes action group and object command. - * @return {ICommandDefinition}: The command definition. - */ - public abstract buildFull(): ICommandDefinition; - - /** - * Gets the "action" that this command builder is building. - * @return {string}: The "create" action string - */ - public abstract getAction(): string; - - /** - * Only constructs the "group" command segment for the document. Use this if the command definition - * document already includes a "create" verb. - * @return {ICommandDefinition} - */ - public build(): ICommandDefinition { - return this.buildProfileSegmentFromSchema(); - } - - /** - * Builds only the "profile" segment from the profile schema. - * @return {ICommandDefinition} - */ - protected abstract buildProfileSegmentFromSchema(): ICommandDefinition ; - - /** - * Construct the operands from the Bright Profile Schema. - * @param {any} properties: The properties set to iterate over looking for operands to add - * @param {ICommandOptionDefinition[]} options: The final option definitions to add. - * @return {ICommandOptionDefinition[]}: The set of returned option definitions - */ - protected buildOptionsFromProfileSchema(properties: any, - options: ICommandOptionDefinition[]): ICommandOptionDefinition[] { - for (const propName of Object.keys(properties)) { - // helper to recursively add any nested option definitions - const findAndAddOptions = (propertiesObject: any, propertyName: string) => { - const field: ICommandProfileProperty = propertiesObject[propertyName]; - if (!(field.optionDefinition == null)) { - options.push(field.optionDefinition); - } - if (!(field.optionDefinitions == null)) { - options = options.concat(field.optionDefinitions); - } - if (field.properties != null) { - for (const nestedProperty of Object.keys(field.properties)) { - findAndAddOptions(field.properties, nestedProperty); - } - } - }; - findAndAddOptions(properties, propName); - } - if (!(this.mProfileConfig.dependencies == null)) { - for (const dependency of this.mProfileConfig.dependencies) { - const description = dependency.description || - "The name of a " + dependency.type + " profile to associate with this profile."; - const dependencyOption: ICommandOptionDefinition = { - name: ProfileUtils.getProfileOption(dependency.type), - aliases: [ProfileUtils.getProfileOptionAlias(dependency.type)], - type: "string", - description, - required: dependency.required - }; - options.push(dependencyOption); - } - } - return options; - } - -} diff --git a/packages/imperative/src/imperative/src/profiles/builders/ProfilesCreateCommandBuilder.ts b/packages/imperative/src/imperative/src/profiles/builders/ProfilesCreateCommandBuilder.ts deleted file mode 100644 index 71714eb419..0000000000 --- a/packages/imperative/src/imperative/src/profiles/builders/ProfilesCreateCommandBuilder.ts +++ /dev/null @@ -1,99 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ProfilesCommandBuilder } from "./ProfilesCommandBuilder"; -import { ICommandDefinition, ICommandProfileTypeConfiguration } from "../../../../cmd"; -import { createProfileCommandDesc, createProfileOptionDesc, createProfileOptionOverwriteDesc, - createProfileDisableDefaultsDesc } from "../../../../messages"; -import { Constants } from "../../../../constants"; -import { TextUtils } from "../../../../utilities"; -import { Logger } from "../../../../logger/index"; -import { ProfilesConstants, ProfileUtils } from "../../../../profiles"; - -/** - * Used to build profile create command definitions. - * Used automatically if you allow the "profiles" command group to be generated - */ -export class ProfilesCreateCommandBuilder extends ProfilesCommandBuilder { - - /** - * Construct the builder based on the schema. - * @param {string} profileType - the type name for the profile - * @param {Logger} logger - logger instance to use for the builder class - * @param {ICommandProfileTypeConfiguration} profileConfig: Imperative profile configuration for this type of profile - */ - constructor(profileType: string, logger: Logger, profileConfig: ICommandProfileTypeConfiguration) { - super(profileType, logger, profileConfig); - } - - /** - * Gets the "action" that this command builder is building. - * @return {string}: The "create" action string - */ - public getAction(): string { - return Constants.CREATE_ACTION; - } - - /** - * Build the full command - includes action group and object command. - * @return {ICommandDefinition}: The command definition. - */ - public buildFull(): ICommandDefinition { - return this.buildProfileSegmentFromSchema(); - } - - /** - * Builds only the "profile" segment from the profile schema. - * @return {ICommandDefinition} - */ - protected buildProfileSegmentFromSchema(): ICommandDefinition { - const profileCommand: ICommandDefinition = { - name: this.mProfileType + "-profile", - aliases: [this.mProfileType], - summary: TextUtils.formatMessage(createProfileCommandDesc.message, - {type: this.mProfileType}), - description: this.mSchema.description, - type: "command", - handler: __dirname + "/../handlers/CreateProfilesHandler", - deprecatedReplacement: ProfilesConstants.DEPRECATE_TO_CONFIG_INIT, - customize: {}, - positionals: [{ - name: Constants.PROFILE_NAME_OPTION, - description: TextUtils.formatMessage(createProfileOptionDesc.message, - { - type: this.mProfileType, - typeOption: ProfileUtils.getProfileOption(this.mProfileType) - }), - type: "string", - required: true, - }], - options: this.buildOptionsFromProfileSchema(this.mSchema.properties, []) - }; - profileCommand.customize[ProfilesConstants.PROFILES_COMMAND_TYPE_KEY] = this.mProfileType; - profileCommand.options.push({ - name: Constants.OVERWRITE_OPTION, aliases: ["ow"], - description: TextUtils.formatMessage(createProfileOptionOverwriteDesc.message, - {type: this.mProfileType}), - type: "boolean" - }); - profileCommand.options.push({ - name: Constants.DISABLE_DEFAULTS_OPTION, aliases: ["dd"], - description: TextUtils.formatMessage(createProfileDisableDefaultsDesc.message, - {type: this.mProfileType}), - type: "boolean" - }); - - if (this.mProfileConfig.createProfileExamples != null) { - profileCommand.examples = this.mProfileConfig.createProfileExamples; - } - return profileCommand; - } -} diff --git a/packages/imperative/src/imperative/src/profiles/builders/ProfilesDeleteCommandBuilder.ts b/packages/imperative/src/imperative/src/profiles/builders/ProfilesDeleteCommandBuilder.ts deleted file mode 100644 index c5174b1f22..0000000000 --- a/packages/imperative/src/imperative/src/profiles/builders/ProfilesDeleteCommandBuilder.ts +++ /dev/null @@ -1,102 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ProfilesCommandBuilder } from "./ProfilesCommandBuilder"; -import { Constants } from "../../../../constants"; -import { ICommandDefinition } from "../../../../cmd"; -import { - deleteProfileActionDesc, - deleteProfileCommandDesc, - deleteProfileExample, - deleteProfileForceOptionDesc, - deleteProfileNameDesc -} from "../../../../messages/index"; -import { ImperativeConfig, TextUtils } from "../../../../utilities"; -import { ProfilesConstants, ProfileUtils } from "../../../../profiles"; - -/** - * Used to build delete profile command definitions. - * Used automatically if you allow the "profiles" command group to be generated - */ -export class ProfilesDeleteCommandBuilder extends ProfilesCommandBuilder { - - /** - * Gets the "action" that this command builder is building. - * @return {string}: The "create" action string - */ - public getAction(): string { - return Constants.DELETE_ACTION; - } - - /** - * Build the full command - includes action group and object command. - * @return {ICommandDefinition}: The command definition. - */ - public buildFull(): ICommandDefinition { - return this.buildProfileSegmentFromSchema(); - } - - /** - * Builds only the "profile" segment from the profile schema. - * @return {ICommandDefinition} - */ - protected buildProfileSegmentFromSchema(): ICommandDefinition { - const profileCommand: ICommandDefinition = { - name: this.mProfileType + "-profile", - aliases: [this.mProfileType], - summary: TextUtils.formatMessage(deleteProfileActionDesc.message, - {type: this.mProfileType}), - description: TextUtils.formatMessage(deleteProfileCommandDesc.message, - {type: this.mProfileType}), - type: "command", - handler: __dirname + "/../handlers/NewDeleteProfilesHandler", - deprecatedReplacement: ProfilesConstants.DEPRECATE_TO_CONFIG_EDIT + - "\n " + ImperativeConfig.instance.config.formMainConfigPathNm({addPath: false}), - customize: {}, - options: [], - positionals: [{ - name: Constants.PROFILE_NAME_OPTION, - description: TextUtils.formatMessage(deleteProfileNameDesc.message, - { - type: this.mProfileType, - typeOption: ProfileUtils.getProfileOption(this.mProfileType) - }), - type: "string", - required: true, - }], - examples: [ - { - options: "profilename", - description: TextUtils.formatMessage(deleteProfileExample.message, - { - type: this.mProfileType, - name: "profilename" - }) - } - ] - }; - profileCommand.customize[ProfilesConstants.PROFILES_COMMAND_TYPE_KEY] = this.mProfileType; - - profileCommand.options.push({ - name: "force", - aliases: [], - description: TextUtils.formatMessage(deleteProfileForceOptionDesc.message, - { - type: this.mProfileType, - typeOption: ProfileUtils.getProfileOption(this.mProfileType) - }), - type: "boolean", - required: false, - }); - - return profileCommand; - } -} diff --git a/packages/imperative/src/imperative/src/profiles/builders/ProfilesListCommandBuilder.ts b/packages/imperative/src/imperative/src/profiles/builders/ProfilesListCommandBuilder.ts deleted file mode 100644 index 084b9b37d3..0000000000 --- a/packages/imperative/src/imperative/src/profiles/builders/ProfilesListCommandBuilder.ts +++ /dev/null @@ -1,104 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ProfilesCommandBuilder } from "./ProfilesCommandBuilder"; -import { Constants } from "../../../../constants"; -import { ICommandDefinition, ICommandProfileTypeConfiguration } from "../../../../cmd"; -import { - listProfileCommandDesc, - listProfileExample, - listProfileExampleShowContents, - listProfileVerboseOptionDesc -} from "../../../../messages"; -import { TextUtils } from "../../../../utilities"; -import { Logger } from "../../../../logger/"; -import { ProfilesConstants } from "../../../../profiles"; - -/** - * Used to build profile update command definitions. - * Used automatically if you allow the "profiles" command group to be generated - */ -export class ProfilesListCommandBuilder extends ProfilesCommandBuilder { - /** - * Construct the builder based on the schema. - * @param profileType - the profile type to generate the command definition for - * @param {Logger} logger - logger instance to use for the builder class - * @param {ICommandProfileTypeConfiguration} profileConfig: Imperative profile configuration for this type of profile - */ - constructor(profileType: string, logger: Logger, profileConfig: ICommandProfileTypeConfiguration) { - super(profileType, logger, profileConfig); - } - - /** - * Gets the "action" that this command builder is building. - * @return {string}: The "create" action string - */ - public getAction(): string { - return Constants.LIST_ACTION; - } - - /** - * Build the full command - includes action group and object command. - * @return {ICommandDefinition}: The command definition. - */ - public buildFull(): ICommandDefinition { - return this.buildProfileSegmentFromSchema(); - } - - /** - * Builds only the "profile" segment from the profile schema. - * @return {ICommandDefinition} - */ - protected buildProfileSegmentFromSchema(): ICommandDefinition { - const profileCommand: ICommandDefinition = { - name: this.mProfileType + "-profiles", - aliases: [this.mProfileType], - summary: TextUtils.formatMessage(listProfileCommandDesc.message, - {type: this.mProfileType}), - description: this.mSchema.description, - type: "command", - handler: __dirname + "/../handlers/ListProfilesHandler", - deprecatedReplacement: ProfilesConstants.DEPRECATE_TO_CONFIG_LIST, - customize: {}, - options: [ - { - name: "show-contents", - aliases: ["sc"], - description: TextUtils.formatMessage(listProfileVerboseOptionDesc.message, - { - type: this.mProfileType - }), - type: "boolean", - required: false - } - - ], - examples: [ - { - options: "", - description: TextUtils.formatMessage(listProfileExample.message, - { - type: this.mProfileType - }), - }, - { - options: "--sc", - description: TextUtils.formatMessage(listProfileExampleShowContents.message, - { - type: this.mProfileType - }), - } - ] - }; - profileCommand.customize[ProfilesConstants.PROFILES_COMMAND_TYPE_KEY] = this.mProfileType; - return profileCommand; - } -} diff --git a/packages/imperative/src/imperative/src/profiles/builders/ProfilesSetCommandBuilder.ts b/packages/imperative/src/imperative/src/profiles/builders/ProfilesSetCommandBuilder.ts deleted file mode 100644 index b628451d16..0000000000 --- a/packages/imperative/src/imperative/src/profiles/builders/ProfilesSetCommandBuilder.ts +++ /dev/null @@ -1,86 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ProfilesCommandBuilder } from "./ProfilesCommandBuilder"; -import { ICommandDefinition } from "../../../../cmd"; -import { TextUtils } from "../../../../utilities"; -import { Constants } from "../../../../constants"; -import { - setGroupWithOnlyProfilesCommandDesc, - setGroupWithOnlyProfilesSummary, - setProfileExample, - setProfileOptionDesc -} from "../../../../messages/index"; -import { ProfilesConstants } from "../../../../profiles"; - -/** - * Used to build "set default profile" command definitions. - * Used automatically if you allow the "profiles" command group to be generated - */ -export class ProfilesSetCommandBuilder extends ProfilesCommandBuilder { - - /** - * Gets the "action" that this command builder is building. - * @return {string}: The "create" action string - */ - public getAction(): string { - return Constants.SET_ACTION; - } - - /** - * Build the full command - includes action group and object command. - * @return {ICommandDefinition}: The command definition. - */ - public buildFull(): ICommandDefinition { - return this.buildProfileSegmentFromSchema(); - } - - /** - * Builds only the "profile" segment from the profile schema. - * @return {ICommandDefinition} - */ - protected buildProfileSegmentFromSchema(): ICommandDefinition { - - const profileCommand: ICommandDefinition = { - name: this.mProfileType + "-profile", - aliases: [this.mProfileType], - summary: TextUtils.formatMessage(setGroupWithOnlyProfilesSummary.message, - {type: this.mProfileType}), - description: TextUtils.formatMessage(setGroupWithOnlyProfilesCommandDesc.message, - {type: this.mProfileType}), - type: "command", - handler: __dirname + "/../handlers/SetDefaultProfilesHandler", - deprecatedReplacement: ProfilesConstants.DEPRECATE_TO_CONFIG_SET, - options: [], - positionals: [{ - name: Constants.PROFILE_NAME_OPTION, - description: TextUtils.formatMessage(setProfileOptionDesc.message, - { - type: this.mProfileType, - }), - type: "string", - required: true, - }], - customize: {}, - examples: [{ - options: "profilename", - description: TextUtils.formatMessage(setProfileExample.message, { - type: this.mProfileType, - name: "profilename" - }), - } - ] - }; - profileCommand.customize[ProfilesConstants.PROFILES_COMMAND_TYPE_KEY] = this.mProfileType; - - return profileCommand; - } -} diff --git a/packages/imperative/src/imperative/src/profiles/builders/ProfilesShowDependenciesCommandBuilder.ts b/packages/imperative/src/imperative/src/profiles/builders/ProfilesShowDependenciesCommandBuilder.ts deleted file mode 100644 index 408d3b9de5..0000000000 --- a/packages/imperative/src/imperative/src/profiles/builders/ProfilesShowDependenciesCommandBuilder.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ProfilesCommandBuilder } from "./ProfilesCommandBuilder"; -import { Constants } from "../../../../constants"; -import { ICommandDefinition } from "../../../../cmd"; -import { deleteProfileNameDesc, showDependenciesCommandDesc } from "../../../../messages"; -import { TextUtils } from "../../../../utilities"; -import { ProfilesConstants, ProfileUtils } from "../../../../profiles"; - -/** - * Used to build profile create command definitions. - * Used automatically if you allow the "profiles" command group to be generated - */ -export class ProfilesShowDependenciesCommandBuilder extends ProfilesCommandBuilder { - - /** - * Gets the "action" that this command builder is building. - * @return {string}: The "create" action string - */ - public getAction(): string { - return Constants.SHOW_DEPS_ACTION; - } - - /** - * Build the full command - includes action group and object command. - * @return {ICommandDefinition}: The command definition. - */ - public buildFull(): ICommandDefinition { - return this.buildProfileSegmentFromSchema(); - } - - /** - * Builds only the "profile" segment from the profile schema. - * @return {ICommandDefinition} - */ - protected buildProfileSegmentFromSchema(): ICommandDefinition { - const profileCommand: ICommandDefinition = { - name: this.mProfileType + "-profile", - aliases: [this.mProfileType], - summary: TextUtils.formatMessage(showDependenciesCommandDesc.message, - {type: this.mProfileType}), - description: this.mSchema.description, - type: "command", - handler: __dirname + "/../handlers/ShowDependenciesProfilesHandler", - customize: {}, - options: [], - positionals: [{ - name: Constants.PROFILE_NAME_OPTION, - description: TextUtils.formatMessage(deleteProfileNameDesc.message, - { - type: this.mProfileType, - typeOption: ProfileUtils.getProfileOption(this.mProfileType) - }), - type: "string", - required: true, - }] - }; - profileCommand.customize[ProfilesConstants.PROFILES_COMMAND_TYPE_KEY] = this.mProfileType; - - return profileCommand; - } -} diff --git a/packages/imperative/src/imperative/src/profiles/builders/ProfilesUpdateCommandBuilder.ts b/packages/imperative/src/imperative/src/profiles/builders/ProfilesUpdateCommandBuilder.ts deleted file mode 100644 index 947fbb5daa..0000000000 --- a/packages/imperative/src/imperative/src/profiles/builders/ProfilesUpdateCommandBuilder.ts +++ /dev/null @@ -1,113 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ProfilesCommandBuilder } from "./ProfilesCommandBuilder"; -import { Constants } from "../../../../constants"; -import { ICommandDefinition } from "../../../../cmd"; -import { createProfileOptionDesc, updateProfileCommandDesc } from "../../../../messages"; -import { TextUtils } from "../../../../utilities"; -import { IProfileProperty, ProfilesConstants, ProfileUtils } from "../../../../profiles"; -import { ICommandProfileProperty } from "../../../../cmd/src/doc/profiles/definition/ICommandProfileProperty"; - -/** - * Used to build profile update command definitions. - * Used automatically if you allow the "profiles" command group to be generated - */ -export class ProfilesUpdateCommandBuilder extends ProfilesCommandBuilder { - - /** - * Gets the "action" that this command builder is building. - * @return {string}: The "create" action string - */ - public getAction(): string { - return Constants.UPDATE_ACTION; - } - - /** - * Build the full command - includes action group and object command. - * @return {ICommandDefinition}: The command definition. - */ - public buildFull(): ICommandDefinition { - return this.buildProfileSegmentFromSchema(); - } - - /** - * Builds only the "profile" segment from the profile schema. - * @return {ICommandDefinition} - */ - protected buildProfileSegmentFromSchema(): ICommandDefinition { - - // clone the properties file before trying to modify them so that we don't affect the original - const updateOnlyProperties: { [key: string]: IProfileProperty } = - JSON.parse(JSON.stringify(this.mSchema.properties)); - for (const propName of Object.keys(updateOnlyProperties)) { - // helper to tweak all nested option definitions - // for updating the profile (marking required options - // optional in case the user does not wish to update them) - const processFieldsForUpdate = (properties: any, propertyName: string) => { - const field: ICommandProfileProperty = properties[propertyName]; - if (!(field.optionDefinition == null)) { - field.optionDefinition.required = false; - field.optionDefinition.absenceImplications = null; - field.optionDefinition.implies = null; - } - if (!(field.optionDefinitions == null)) { - for (const anOption of field.optionDefinitions) { - if (!(anOption.required == null)) { - anOption.required = false; - anOption.absenceImplications = null; - anOption.implies = null; - } - } - } - if (field.properties != null) { - for (const nestedProperty of Object.keys(field.properties)) { - processFieldsForUpdate(field.properties, nestedProperty); - } - } - }; - processFieldsForUpdate(updateOnlyProperties, propName); - } - const profileCommand: ICommandDefinition = { - name: this.mProfileType + "-profile", - aliases: [this.mProfileType], - summary: TextUtils.formatMessage(updateProfileCommandDesc.message, - {type: this.mProfileType}), - description: this.mSchema.description, - type: "command", - handler: __dirname + "/../handlers/UpdateProfilesHandler", - deprecatedReplacement: ProfilesConstants.DEPRECATE_TO_CONFIG_SET, - customize: {}, - positionals: [{ - name: Constants.PROFILE_NAME_OPTION, - description: TextUtils.formatMessage(createProfileOptionDesc.message, - { - type: this.mProfileType, - typeOption: ProfileUtils.getProfileOption(this.mProfileType) - }), - type: "string", - required: true, - }], - options: this.buildOptionsFromProfileSchema(updateOnlyProperties, []), - }; - profileCommand.customize[ProfilesConstants.PROFILES_COMMAND_TYPE_KEY] = this.mProfileType; - - if (this.mProfileConfig.updateProfileExamples != null) { - profileCommand.examples = this.mProfileConfig.updateProfileExamples; - } - - // We don't want to override existing settings with defaultValue for an option - for (const option of profileCommand.options) { - delete option.defaultValue; - } - return profileCommand; - } -} diff --git a/packages/imperative/src/imperative/src/profiles/builders/ProfilesValidateCommandBuilder.ts b/packages/imperative/src/imperative/src/profiles/builders/ProfilesValidateCommandBuilder.ts deleted file mode 100644 index 871cbc9217..0000000000 --- a/packages/imperative/src/imperative/src/profiles/builders/ProfilesValidateCommandBuilder.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ProfilesCommandBuilder } from "./ProfilesCommandBuilder"; -import { ICommandDefinition, ICommandProfileTypeConfiguration } from "../../../../cmd"; -import { Constants } from "../../../../constants"; -import { deleteProfileNameDesc, validateProfileCommandDesc } from "../../../../messages"; -import { ImperativeConfig, TextUtils } from "../../../../utilities"; -import { Logger } from "../../../../logger/index"; -import { ProfilesConstants, ProfileUtils, ProfileValidator } from "../../../../profiles"; - -/** - * Used to build profile validate command definitions. - * Used automatically if you allow the "profiles" command group to be generated - */ -export class ProfilesValidateCommandBuilder extends ProfilesCommandBuilder { - - /** - * Construct the builder based on the schema. - * @param profileType - the name of the profile type to build the command for - * @param {Logger} logger - logger to use while building command definition - * @param {ICommandProfileTypeConfiguration} profileConfig: Imperative profile configuration for this type of profile - */ - constructor(profileType: string, logger: Logger, profileConfig: ICommandProfileTypeConfiguration) { - super(profileType, logger, profileConfig); - } - - /** - * Gets the "action" that this command builder is building. - * @return {string}: The "create" action string - */ - public getAction(): string { - return Constants.VALIDATE_ACTION; - } - - /** - * Build the full command - includes action group and object command. - * @return {ICommandDefinition}: The command definition. - */ - public buildFull(): ICommandDefinition { - return this.buildProfileSegmentFromSchema(); - } - - /** - * Builds only the "profile" segment from the profile schema. - * @return {ICommandDefinition} - */ - protected buildProfileSegmentFromSchema(): ICommandDefinition { - if (this.mProfileConfig.validationPlanModule == null) { - return undefined; - } - const profileCommand: ICommandDefinition = { - name: this.mProfileType + "-profile", - aliases: [this.mProfileType], - summary: TextUtils.formatMessage(validateProfileCommandDesc.message, - {type: this.mProfileType}), - description: TextUtils.formatMessage(validateProfileCommandDesc.message, - {type: this.mProfileType}), - type: "command", - handler: __dirname + "/../handlers/ValidateProfileHandler", - deprecatedReplacement: ProfilesConstants.DEPRECATE_TO_CONFIG_EDIT + - "\n " + ImperativeConfig.instance.config.formMainConfigPathNm({addPath: false}), - customize: {}, - options: [ProfileValidator.PRINT_PLAN_OPTION], - positionals: [{ - name: Constants.PROFILE_NAME_OPTION, - description: TextUtils.formatMessage(deleteProfileNameDesc.message, - { - type: this.mProfileType, - typeOption: ProfileUtils.getProfileOption(this.mProfileType) - }), - type: "string", - required: false - }] - }; - profileCommand.customize[ProfilesConstants.PROFILES_COMMAND_TYPE_KEY] = this.mProfileType; - - - return profileCommand; - } -} diff --git a/packages/imperative/src/imperative/src/profiles/handlers/CreateProfilesHandler.ts b/packages/imperative/src/imperative/src/profiles/handlers/CreateProfilesHandler.ts deleted file mode 100644 index dc588f06a8..0000000000 --- a/packages/imperative/src/imperative/src/profiles/handlers/CreateProfilesHandler.ts +++ /dev/null @@ -1,83 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { overroteProfileMessage, profileCreatedSuccessfullyAndPath, profileReviewMessage } from "../../../../messages"; -import { Imperative } from "../../Imperative"; -import { IProfileSaved, ISaveProfileFromCliArgs, ProfilesConstants } from "../../../../profiles"; -import { CliProfileManager, ICommandHandler, IHandlerParameters } from "../../../../cmd"; - -import { Constants } from "../../../../constants"; -import { TextUtils } from "../../../../utilities"; - -/** - * Handler that allows creation of a profile from command line arguments. Intended for usage with the automatically - * generated profile create commands, but can be used otherwise. - * @export - * @class CreateProfilesHandler - * @implements {ICommandHandler} - */ -export default class CreateProfilesHandler implements ICommandHandler { - /** - * Create a profile from command line arguments. - * @param {IHandlerParameters} commandParameters - Standard Imperative command handler parameters - see the - * interface for full details - * @memberof CreateProfilesHandler - */ - public async process(commandParameters: IHandlerParameters) { - const profileType: string = commandParameters.definition.customize[ProfilesConstants.PROFILES_COMMAND_TYPE_KEY]; - let profileManager: CliProfileManager; - - try { - profileManager = Imperative.api.profileManager(profileType); - } catch (error) { - // profileIO error is thrown when calling old profile functions in team config mode. - commandParameters.response.console.error( - "An error occurred trying to create a profile.\n" + error.message - ); - return; - } - - const profileName = commandParameters.arguments[Constants.PROFILE_NAME_OPTION]; - const createParms: ISaveProfileFromCliArgs = { - name: profileName, - type: profileType, - args: commandParameters.arguments, - overwrite: commandParameters.arguments.overwrite, - disableDefaults: commandParameters.arguments.disableDefaults, - profile: {} - }; - /** - * Create the profile based on the command line arguments passed - */ - const createResponse: IProfileSaved = await profileManager.save(createParms); - - /** - * Indicate to the user (if specified) that the profile was overwritten - */ - if (createResponse.overwritten) { - commandParameters.response.console.log(overroteProfileMessage.message, { - profileOption: commandParameters - .arguments[Constants.PROFILE_NAME_OPTION] - }); - } - - /** - * Formulate th remainder of the response - which - */ - commandParameters.response.console.log(profileCreatedSuccessfullyAndPath.message); - commandParameters.response.console.log(createResponse.path); - commandParameters.response.console.log(""); - commandParameters.response.console.log(TextUtils.prettyJson(createResponse.profile, - undefined, undefined, "\n")); - commandParameters.response.console.log(profileReviewMessage.message); - } -} - diff --git a/packages/imperative/src/imperative/src/profiles/handlers/ListProfilesHandler.ts b/packages/imperative/src/imperative/src/profiles/handlers/ListProfilesHandler.ts deleted file mode 100644 index 2d33126600..0000000000 --- a/packages/imperative/src/imperative/src/profiles/handlers/ListProfilesHandler.ts +++ /dev/null @@ -1,84 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { Imperative } from "../../../"; -import { ProfilesConstants } from "../../../../profiles/src/constants/ProfilesConstants"; -import { CliProfileManager, ICommandHandler, IHandlerParameters } from "../../../../cmd"; -import { IProfileLoaded } from "../../../.."; - -/** - * Handler for the auto-generated list profiles command. - */ -export default class ListProfilesHandler implements ICommandHandler { - - /** - * The process command handler for the "list profiles" command. - * @return {Promise}: The promise to fulfill when complete. - */ - public async process(params: IHandlerParameters): Promise { - let profileManager: CliProfileManager; - - // Extract the profile type - const profileType: string = params.definition.customize[ProfilesConstants.PROFILES_COMMAND_TYPE_KEY]; - - try { - // Extract the profile manager - profileManager = Imperative.api.profileManager(profileType); - } catch (error) { - // profileIO error is thrown when calling old profile functions in team config mode. - params.response.console.error( - "An error occurred trying to list profiles.\n" + error.message - ); - return; - } - - // Extract the default profile - const defaultName: string = profileManager.getDefaultProfileName(); - - // Load all profiles for the type contained in the manager - const loadResults: IProfileLoaded[] = await profileManager.loadAll( - {noSecure: true, typeOnly: true} - ); - - // Set the data object - params.response.data.setMessage(`"${loadResults.length}" profiles loaded for type "${profileType}"`); - params.response.data.setObj(loadResults); - - // Construct the format print list - const print = []; - for (const result of loadResults) { - if (result.name === defaultName) { - result.name += " (default) "; - } - - print.push({ - name: result.name, - contents: result.profile - }); - - } - - // Format the results accord to the contents - if (params.arguments.showContents) { - params.response.format.output({ - output: print, - format: "object" - }); - } else { - params.response.format.output({ - output: print, - fields: ["name"], - format: "list" - }); - } - } -} - diff --git a/packages/imperative/src/imperative/src/profiles/handlers/NewDeleteProfilesHandler.ts b/packages/imperative/src/imperative/src/profiles/handlers/NewDeleteProfilesHandler.ts deleted file mode 100644 index ac12434759..0000000000 --- a/packages/imperative/src/imperative/src/profiles/handlers/NewDeleteProfilesHandler.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IHandlerParameters } from "../../../../cmd"; -import { Imperative } from "../../Imperative"; -import { Constants } from "../../../../constants"; -import { IProfileDeleted, ProfilesConstants } from "../../../../profiles"; - -export default class NewDeleteProfilesHandler { - public async process(commandParameters: IHandlerParameters) { - const profileType = commandParameters.definition.customize[ProfilesConstants.PROFILES_COMMAND_TYPE_KEY]; - const profileName: string = commandParameters.arguments[Constants.PROFILE_NAME_OPTION]; - let deleted: IProfileDeleted; - - try { - deleted = await Imperative.api.profileManager(profileType).delete({ - name: profileName, - rejectIfDependency: !commandParameters.arguments.force || false - }); - } catch (error) { - // profileIO error is thrown when calling old profile functions in team config mode. - commandParameters.response.console.error( - "An error occurred trying to delete a profile.\n" + error.message - ); - return; - } - - if (!deleted.defaultCleared) { - commandParameters.response.console.log(`Your profile named ${profileName} of type ${profileType} was successfully deleted.`); - } else { - commandParameters.response.console.log(`Your default profile named ${profileName} of type ${profileType} was successfully deleted.\n` + - `Because you deleted it, the default profile for type ${profileType} has been cleared.\nTo set a new default profile, run "zowe ` + - `profiles set-default ${profileType} ".`); - } - } -} diff --git a/packages/imperative/src/imperative/src/profiles/handlers/OldDeleteProfilesHandler.ts b/packages/imperative/src/imperative/src/profiles/handlers/OldDeleteProfilesHandler.ts deleted file mode 100644 index e7891d4028..0000000000 --- a/packages/imperative/src/imperative/src/profiles/handlers/OldDeleteProfilesHandler.ts +++ /dev/null @@ -1,260 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -// // import { isNullOrUndefined } from "util"; -// import { CommandResponse, ICommandHandler, IHandlerParameters } from "../../../../cmd"; -// import { Constants } from "../../../../constants"; -// import { ProfileManager } from "../../ProfileManager"; -// import { -// profileDeletedSuccessfully, -// profileDeleteErrorDetails, -// profileDeleteErrorHeader, -// profileNotDeletedMessage, -// unableToDeleteProfile, -// unableToFindProfile -// } from "../../../../messages"; -// import { TextUtils } from "../../../../utilities"; -// import { IProfileDeleted } from "../../doc/response/IProfileDeleted"; -// import { IProfile } from "../../../index"; -// import { IProfileLoaded } from "../../doc/response/IProfileLoaded"; -// import { Imperative } from "../../../../index"; -// import { ProfileUtils } from "../../ProfileUtils"; -// import { ProfilesConstants } from "../../constants/ProfilesConstants"; - -// /** -// * Handler for the auto-generated delete profiles command. -// * Deletes requested user configuration profiles -// */ -// export default class DeleteProfilesHandler implements ICommandHandler { -// private rejectCommand: any; -// private response: CommandResponse; - -// /** -// * The process command handler for the "delete profile" command. -// * @return {Promise}: The promise to fulfill when complete. -// */ -// public process(commandParameters: IHandlerParameters): Promise { - -// /** -// * Invoke the modules profile creator. -// */ -// const errors: string[] = []; -// const shouldForce: boolean = commandParameters.arguments.force; -// const profileList: Map = new Map(); -// const profileType = commandParameters.definition.customize[ProfilesConstants.PROFILES_COMMAND_TYPE_KEY]; -// const profileSpecified: string = commandParameters.arguments[Constants.PROFILE_NAME_OPTION]; - -// let loadedProfile: IProfile; -// return new Promise((commandComplete, rejectCommand) => { -// this.rejectCommand = rejectCommand; -// new ProfileManager(profileType) -// .loadProfile({ name: profileSpecified }).then((profileResponse) => { -// loadedProfile = profileResponse.profile; -// profileList.set(profileType, [loadedProfile]); -// const loadPromises: Array> = []; -// if (!isNullOrUndefined(loadedProfile.dependencies) && -// commandParameters.arguments[Constants.PROFILE_DELETE_PROFILE_DEPS]) { -// for (const entry of loadedProfile.dependencies) { -// const loadPromise: Promise = -// new ProfileManager({ -// type: profileType, -// allTypeConfigs: Imperative.loadedConfig.profiles, -// profileDir: ProfileUtils.constructProfilesDir() -// }).loadProfile({ name: entry.name }); -// loadPromises.push(loadPromise); -// loadPromise.then((profileDeleteResponse) => { -// if (isNullOrUndefined(profileList.get(entry.name))) { -// profileList.set(entry.type, [profileDeleteResponse.profile]); -// } else { -// profileList.set(entry.type, profileList.get(entry.type) -// .concat(profileDeleteResponse.profile)); -// } -// // if (profileDeleteResponse.success) { -// // if (isNullOrUndefined(profileList.get(entry.name))) { -// // profileList.set(entry.type, [profileDeleteResponse.profile]); -// // } -// // else { -// // profileList.set(entry.type, profileList.get(entry.type) -// // .concat(profileDeleteResponse.profile)); -// // } -// // } -// // else { -// // errors.push("Could not load the dependent profile " + entry.name + -// // " from module " + entry.type); -// // } -// }).catch((loadErr) => { -// rejectCommand(loadErr); -// }); -// } -// } -// } -// Promise.all(loadPromises).then((values) => { -// if (!shouldForce) { -// this.displayPrompts(profileList, commandParameters, errors); -// } -// else { -// this.deleteWithoutPrompts(profileList, commandParameters, errors); -// } -// }); -// }).catch((loadErr) => { -// // if (shouldForce) { -// // if (!isNullOrUndefined(profileResponse.profile)) { -// // profileList.set(profileType, [profileResponse.profile]); -// // this.deleteWithoutPrompts(profileList, commandParameters, errors); -// // } else { -// // commandParameters.response.writeErrorHeader(profileDeleteErrorHeader.message); -// // commandParameters.response.console.error( -// // unableToFindProfile.message, profileResponse.message); -// // commandParameters.response.console.error("Manual remediation is recommended."); -// // commandParameters.response.failed(); -// // } -// // } -// // else { -// commandParameters.response.appendError({ -// msg: loadErr.message, -// additionalDetails: "You can use the --force operand to " + -// "force deletion of the profile in error." -// }); -// this.rejectCommand(); -// // } -// }); -// }); -// } - -// private deleteWithoutPrompts(profileList: Map, commandParameters: IHandlerParameters, -// errors: string[]) { -// const profileModule = new ProfileManager(commandParameters.definition.customize[ProfilesConstants.PROFILES_COMMAND_TYPE_KEY]); -// const deletePromises: Array> = []; -// const successes: string[] = []; -// profileList.forEach((profiles, module, map) => { -// for (const profileEntry of profiles) { -// const profile: IProfile = profileEntry; -// const deleteOp: Promise = profileModule.deleteProfile({profile}); -// deletePromises.push(deleteOp); -// deleteOp.then((profileDeleted) => { -// /** -// * TODO: Work this out with the new promise scheme -// */ -// // if (profileDeleted.success) { -// // // mLogger.trace(`Successfully deleted profile ${profile.profileName}`); -// // successes.push(profile.name); -// // } -// // else { -// // // mLogger.trace(`Failed to delete the profile ${profile.profileName}`); -// // errors.push(`Error deleting profile ${profileDeleted.profilePath}.`); -// // } -// }); -// } -// }); -// Promise.all(deletePromises).then((values) => { - -// if (errors.length === 0 && successes.length > 0) { -// commandParameters.response.console.log( -// profileDeletedSuccessfully.message, successes.join()); -// } -// else if (errors.length === 0 && successes.length === 0) { -// commandParameters.response.console.log(profileNotDeletedMessage.message); -// } -// else { -// commandParameters.response.appendError({ -// msg: unableToDeleteProfile.message, -// additionalDetails: TextUtils.formatMessage( -// profileDeleteErrorDetails.message, -// {errorDetails: errors.join("\n")}) -// }); -// this.rejectCommand(); -// } -// }); -// } - -// private displayPrompts(profileList: Map, commandParameters: IHandlerParameters, -// errors: string[]) { -// const prompt: any = require("prompt"); -// prompt.message = "Attention"; -// let profileCount: number = 0; -// const successes: string[] = []; - -// const profileType = commandParameters.definition.customize[ProfilesConstants.PROFILES_COMMAND_TYPE_KEY]; -// const profileManager = new ProfileManager(profileType); -// const deletePromises: Array> = []; -// profileList.forEach((profiles, module, map) => { -// for (const profileEntry of profiles) { -// const theProfile: IProfile = profileEntry; -// const promptSchema = { -// properties: { -// deleteConfirmation: { -// description: `Please confirm deletion of the profile` + -// ` "${theProfile.name}". This action cannot be undone. (true/false)`, -// type: "boolean", -// pattern: /^[YyNn]+$/, -// message: "Please enter true or false to confirm the profile deletion.", -// required: true -// } -// } -// }; -// prompt.start(); -// prompt.get(promptSchema, (err: any, result: any) => { -// // this.mLogger.debug("User entered " + result.deleteConfirmation + " for the profile " + profile.profileName); -// if (result.deleteConfirmation === true) { -// // const deleteOp: Promise = profileManager.deleteProfile(profile); -// const deleteOp: Promise = profileManager.deleteProfile({ -// profile: theProfile -// }); -// deletePromises.push(deleteOp); -// deleteOp.then((profileDeleted) => { -// /** -// * TODO: work this out with the new promise scheme -// */ -// // if (profileDeleted.success) { -// // // mLogger.trace(`Successfully deleted profile ${profile.profileName}`); -// // successes.push(profile.name); -// // } -// // else { -// // // mLogger.trace(`Failed to delete the profile ${profile.profileName}`); -// // errors.push(`Error deleting profile ${profileDeleted.profilePath}.`); -// // } -// }); -// Promise.all([deleteOp]).then((values) => { -// // do nothing -// }); -// profileCount++; -// } -// else { -// profileCount++; -// } - -// if (profileCount === profileList.get(profileType).length) { -// Promise.all(deletePromises).then((values) => { - -// if (errors.length === 0 && successes.length > 0) { -// commandParameters.response.console.log(profileDeletedSuccessfully.message, successes.join()); -// } -// else if (errors.length === 0 && successes.length === 0) { -// commandParameters.response.console.log(profileNotDeletedMessage.message); -// } -// else { -// commandParameters.response.appendError({ -// msg: unableToDeleteProfile.message, -// additionalDetails: TextUtils.formatMessage( -// profileDeleteErrorDetails.message, -// {errorDetails: errors.join("\n")}) -// }); -// this.rejectCommand(); -// } -// }); -// prompt.stop(); -// } -// }); -// } -// }); -// } -// } - diff --git a/packages/imperative/src/imperative/src/profiles/handlers/SetDefaultProfilesHandler.ts b/packages/imperative/src/imperative/src/profiles/handlers/SetDefaultProfilesHandler.ts deleted file mode 100644 index 7cdb46ea20..0000000000 --- a/packages/imperative/src/imperative/src/profiles/handlers/SetDefaultProfilesHandler.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { Imperative } from "../../Imperative"; -import { ProfilesConstants } from "../../../../profiles"; -import { ICommandHandler, IHandlerParameters } from "../../../../cmd"; -import { Constants } from "../../../../constants"; -/** - * Handler for the auto generated commands to set the default profile for a type - * The default profile is loaded when no specific profile name is specified - */ -export default class SetDefaultProfilesHandler implements ICommandHandler { - /** - * process the set default profile command arguments - * @return {Promise}: The promise to fulfill when complete. - */ - public process(commandParameters: IHandlerParameters): Promise { - return new Promise((commandComplete, commandRejected) => { - /** - * Get the loaded module for the command being issued and set the default profile. - */ - const profileType: string = commandParameters.definition.customize[ProfilesConstants.PROFILES_COMMAND_TYPE_KEY]; - const profileSpecified: string = commandParameters.arguments[Constants.PROFILE_NAME_OPTION]; - let invoked: boolean = false; - try { - Imperative.api.profileManager(profileType).setDefault(profileSpecified); - commandParameters.response.console.log(`The default profile for ${profileType} set to ` + - `${profileSpecified}`); - } catch (error) { - const err: string = `Error occurred while setting default profile for ` + - `${profileType}.\n${error.message}`; - commandParameters.response.console.error(err); - invoked = true; - commandRejected(); - } - - // Fulfill the promise - if (!invoked) { - commandComplete(); - } - }); - } - -} diff --git a/packages/imperative/src/imperative/src/profiles/handlers/ShowDependenciesProfilesHandler.ts b/packages/imperative/src/imperative/src/profiles/handlers/ShowDependenciesProfilesHandler.ts deleted file mode 100644 index 338699071a..0000000000 --- a/packages/imperative/src/imperative/src/profiles/handlers/ShowDependenciesProfilesHandler.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ICommandHandler, IHandlerParameters } from "../../../../cmd"; - -/** - * Handler for the auto-generated show dependencies command - */ -export default class ShowDependenciesProfilesHandler implements ICommandHandler { - - /** - * The process command handler for the "show dependencies" command. - * @return {Promise}: The promise to fulfill when complete. - */ - public process(commandParameters: IHandlerParameters): Promise { - return new Promise((commandComplete) => { - - // Do nothing - // Need for this minimized by list --verbose - commandComplete(); - }); - } -} diff --git a/packages/imperative/src/imperative/src/profiles/handlers/UpdateProfilesHandler.ts b/packages/imperative/src/imperative/src/profiles/handlers/UpdateProfilesHandler.ts deleted file mode 100644 index 6ec64af53f..0000000000 --- a/packages/imperative/src/imperative/src/profiles/handlers/UpdateProfilesHandler.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { overroteProfileMessage, profileUpdatedSuccessfullyAndPath, profileReviewMessage } from "../../../../messages"; -import { Imperative } from "../../Imperative"; -import { IProfileUpdated, ProfilesConstants } from "../../../../profiles"; -import { ICommandHandler, IHandlerParameters } from "../../../../cmd"; -import { Constants } from "../../../../constants"; -import { TextUtils } from "../../../../utilities"; - -/** - * Handler for the auto-generated update profile commands - * Allows the user to simply update an existing configuration profile - */ -export default class UpdateProfilesHandler implements ICommandHandler { - /** - * The process command handler for the "update profile" command. - * @return {Promise}: The promise to fulfill when complete. - */ - public async process(commandParameters: IHandlerParameters): Promise { - - /** - * Invoke the modules profile creator. - */ - const profileType = commandParameters.definition.customize[ProfilesConstants.PROFILES_COMMAND_TYPE_KEY]; - const profileSpecified: string = commandParameters.arguments[Constants.PROFILE_NAME_OPTION]; - let profileUpdated: IProfileUpdated; - - try { - profileUpdated = await Imperative.api.profileManager(profileType).update({ - name: profileSpecified, - args: commandParameters.arguments, - merge: true - }); - } catch (error) { - // profileIO error is thrown when calling old profile functions in team config mode. - commandParameters.response.console.error( - "An error occurred trying to update a profile.\n" + error.message - ); - return; - } - - commandParameters.response.console.log(overroteProfileMessage.message, { - profileOption: commandParameters.arguments[Constants.PROFILE_NAME_OPTION] - }); - commandParameters.response.console.log(profileUpdatedSuccessfullyAndPath.message); - commandParameters.response.console.log(profileUpdated.path); - commandParameters.response.console.log(""); - commandParameters.response.console.log(TextUtils.prettyJson(profileUpdated.profile, - undefined, undefined, "\n")); - commandParameters.response.console.log(profileReviewMessage.message); - - } -} diff --git a/packages/imperative/src/imperative/src/profiles/handlers/ValidateProfileHandler.ts b/packages/imperative/src/imperative/src/profiles/handlers/ValidateProfileHandler.ts deleted file mode 100644 index 9900f66c9f..0000000000 --- a/packages/imperative/src/imperative/src/profiles/handlers/ValidateProfileHandler.ts +++ /dev/null @@ -1,129 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { CliProfileManager, ICommandHandler, IHandlerParameters } from "../../../../cmd"; -import { IImperativeError, ImperativeError } from "../../../../error"; -import { Imperative } from "../../../index"; -import { - IProfileValidationPlan, - IProfileValidationReport, - IProfileValidationTask, - ProfilesConstants, - ProfileValidator -} from "../../../../profiles"; -import { Logger } from "../../../../logger"; -import { ImperativeConfig } from "../../../../utilities"; - -/** - * Generic handler for validating a profile and printing a report in response - */ -export default class ValidateProfileHandler implements ICommandHandler { - /** - * Get an instance of the imperative logger. - * @private - * @type {Logger} - * @memberof ValidateProfileHandler - */ - private mLogger: Logger = Imperative.api.imperativeLogger; - - public async process(params: IHandlerParameters): Promise { - - const profileType = params.definition.customize[ProfilesConstants.PROFILES_COMMAND_TYPE_KEY]; - - let manager: CliProfileManager; - try { - // Extract the profile manager - manager = Imperative.api.profileManager(profileType); - } catch (error) { - // profileIO error is thrown when calling old profile functions in team config mode. - params.response.console.error( - "An error occurred trying to validate a profile.\n" + error.message - ); - return; - } - - let profileName = manager.getDefaultProfileName(); - - // if the user specified a specific profile, we can determine the name of the profile from that - if (params.arguments.profileName != null) { - profileName = params.arguments.profileName; - } - - const profileToValidate = (await manager.load({failNotFound: true, name: profileName})).profile; - let plan: IProfileValidationPlan; - try { - // load the definition of the plan from the specified file path - // this will return the class definition of the plan - const planModule = Imperative.getProfileConfiguration(profileType).validationPlanModule; - plan = require(planModule); - // instantiate the plan object - plan = new (plan as any)(); - } catch (e) { - const planLoadErr: IImperativeError = { - msg: "An error was encountered trying to load the plan to validate the Brightside profile.", - additionalDetails: e.message, - causeErrors: e - }; - throw new ImperativeError(planLoadErr); - } - - // if the user just requested that we print the plan rather than actually validate the profile - if (params.arguments[ProfileValidator.PRINT_PLAN_OPTION.name]) { - - Logger.getImperativeLogger().debug("Printed plan for profile validation requested"); - params.response.console.log(Buffer.from(ProfileValidator.getTextDisplayForPlan(plan, profileToValidate, - ImperativeConfig.instance.loadedConfig.primaryTextColor))); - - const cleanTaskForJSONOutput = (task: IProfileValidationTask) => { - delete task.taskFunction; - if (!(task.dependentTasks == null)) { - for (const dependent of task.dependentTasks) { - cleanTaskForJSONOutput(dependent); - } - } - }; - // add the object version of the plan to the JSON response, without the task functions - // since they can't be printed - for (const task of plan.tasks) { - cleanTaskForJSONOutput(task); - } - params.response.data.setObj(plan); - return; - } - let report: IProfileValidationReport; - try { - const promise = ProfileValidator.validate(profileToValidate, - plan, ImperativeConfig.instance.loadedConfig.productDisplayName); - params.response.progress.startBar({task: promise.progress}); - report = await promise; - params.response.data.setObj(report); - const reportText = Buffer.from(ProfileValidator.getTextDisplayForReport(report, plan, - ImperativeConfig.instance.loadedConfig.productDisplayName, - ImperativeConfig.instance.loadedConfig.primaryTextColor, - profileName, - profileType)); - params.response.console.log(reportText); - } catch (validateError) { - const unexpectedError: IImperativeError = { - msg: "Encountered an unexpected exception " + - "while validating your profile. ", - additionalDetails: validateError.message, - causeErrors: validateError - }; - params.response.console.error("Failed to validate profile due to unexpected exception"); - throw new ImperativeError(unexpectedError); - } - if (report.overallResult !== "OK") { - throw new ImperativeError({msg: "The profile validation was not successful"}); - } - } - -} diff --git a/packages/imperative/src/index.ts b/packages/imperative/src/index.ts index 334969ff98..4fe4232ed7 100644 --- a/packages/imperative/src/index.ts +++ b/packages/imperative/src/index.ts @@ -13,14 +13,15 @@ export * from "./cmd"; export * from "./config"; export * from "./console"; export * from "./constants"; +export * from "./events"; export * from "./error"; export * from "./expect"; export * from "./imperative"; +// export * from "./interfaces"; export * from "./io"; export * from "./logger"; export * from "./messages"; export * from "./operations"; -export * from "./interfaces"; export * from "./profiles"; export * from "./rest"; export * from "./security"; diff --git a/packages/imperative/src/io/__tests__/IO.unit.test.ts b/packages/imperative/src/io/__tests__/IO.unit.test.ts index 880a40a1ea..717ba989ea 100644 --- a/packages/imperative/src/io/__tests__/IO.unit.test.ts +++ b/packages/imperative/src/io/__tests__/IO.unit.test.ts @@ -116,7 +116,7 @@ describe("IO tests", () => { return; // do nothing but pretend to write }) as any); IO.createDirSync("pretend/to/create"); - expect(fnFm).toBeCalled(); + expect(fnFm).toHaveBeenCalled(); }); it("should not create a dir if file exists", () => { @@ -126,8 +126,8 @@ describe("IO tests", () => { return; // do nothing but pretend to write }) as any); IO.createDirSync("pretend/already/exists"); - expect(existsSyncSpy).toBeCalled(); - expect(fnFm).not.toBeCalled(); + expect(existsSyncSpy).toHaveBeenCalled(); + expect(fnFm).not.toHaveBeenCalled(); }); it("should get an error for no input on createDirsSync", () => { @@ -151,7 +151,7 @@ describe("IO tests", () => { return pathSegments[0]; }); const willBeADir = ["pretend", "to", "create"]; - const dir = willBeADir.join(IO.FILE_DELIM); + const dir = willBeADir.join(path.posix.sep); IO.createDirsSync(dir); expect(fnFm).toHaveBeenCalledTimes(willBeADir.length); }); @@ -167,7 +167,7 @@ describe("IO tests", () => { return pathSegments[0]; }); const willBeADir = ["pretend", "to", "create"]; - const dir = willBeADir.join(IO.FILE_DELIM); + const dir = willBeADir.join(path.posix.sep); IO.createDirsSync(dir); expect(fnFm).not.toHaveBeenCalled(); }); @@ -187,7 +187,7 @@ describe("IO tests", () => { fnPr.mockImplementation((...pathSegments: any[]) => { return pathSegments[0]; }); - const dir = willBeADir.join(IO.FILE_DELIM); + const dir = willBeADir.join(path.posix.sep); IO.createDirsSync(dir); expect(fnFm).toHaveBeenCalledTimes(willBeADir.length - 1); }); @@ -204,12 +204,12 @@ describe("IO tests", () => { }); const fnPd = jest.mocked(path.dirname); fnPd.mockImplementation(((...pathSegments: any[]) => { - const toDir: string[] = pathSegments[0].split(IO.FILE_DELIM); + const toDir: string[] = pathSegments[0].split(path.posix.sep); toDir.pop(); - return toDir.join(IO.FILE_DELIM); + return toDir.join(path.posix.sep); }) as any); const willBeADir = ["pretend", "to", "create", "test.txt"]; - const dir = willBeADir.join(IO.FILE_DELIM); + const dir = willBeADir.join(path.posix.sep); IO.createDirsSyncFromFilePath(dir); expect(fnFm).toHaveBeenCalledTimes(willBeADir.length - 1); }); @@ -226,12 +226,12 @@ describe("IO tests", () => { }); const fnPd = jest.mocked(path.dirname); fnPd.mockImplementation(((...pathSegments: any[]) => { - const toDir: string[] = pathSegments[0].split(IO.FILE_DELIM); + const toDir: string[] = pathSegments[0].split(path.posix.sep); toDir.pop(); - return toDir.join(IO.FILE_DELIM); + return toDir.join(path.posix.sep); }) as any); const willBeADir = ["pretend", "to", "create", "test.txt"]; - const dir = willBeADir.join(IO.FILE_DELIM); + const dir = willBeADir.join(path.posix.sep); IO.createDirsSyncFromFilePath(dir); expect(fnFm).not.toHaveBeenCalled(); }); @@ -253,11 +253,11 @@ describe("IO tests", () => { }); const fnPd = jest.mocked(path.dirname); fnPd.mockImplementation(((...pathSegments: any[]) => { - const toDir: string[] = pathSegments[0].split(IO.FILE_DELIM); + const toDir: string[] = pathSegments[0].split(path.posix.sep); toDir.pop(); - return toDir.join(IO.FILE_DELIM); + return toDir.join(path.posix.sep); }) as any); - const dir = willBeADir.join(IO.FILE_DELIM); + const dir = willBeADir.join(path.posix.sep); IO.createDirsSyncFromFilePath(dir); expect(fnFm).toHaveBeenCalledTimes(willBeADir.length - 2); }); diff --git a/packages/imperative/src/io/src/IO.ts b/packages/imperative/src/io/src/IO.ts index 327335ce00..8159c7bb0a 100644 --- a/packages/imperative/src/io/src/IO.ts +++ b/packages/imperative/src/io/src/IO.ts @@ -30,11 +30,12 @@ export class IO { /** * File delimiter + * @deprecated Use `path.posix.sep` instead or `path.sep` for better cross-platform support * @static * @type {string} * @memberof IO */ - public static readonly FILE_DELIM: string = "/"; + public static readonly FILE_DELIM: string = path.posix.sep; /** * UTF8 identifier @@ -133,12 +134,12 @@ export class IO { ImperativeExpect.toBeDefinedAndNonBlank(dir, "dir"); // we're splitting on a specific separator character, so replace \ with / // before splitting - const dirs = path.resolve(dir).replace(/\\/g, IO.FILE_DELIM).split(IO.FILE_DELIM); + const dirs = path.resolve(dir).replace(/\\/g, path.posix.sep).split(path.posix.sep); let createDir: string = ""; for (const crDir of dirs) { - createDir += (crDir + IO.FILE_DELIM); + createDir += crDir + path.posix.sep; IO.createDirSync(createDir); } } diff --git a/packages/imperative/src/logger/__tests__/Logger.unit.test.ts b/packages/imperative/src/logger/__tests__/Logger.unit.test.ts index 4e2ef1a769..81db1db59d 100644 --- a/packages/imperative/src/logger/__tests__/Logger.unit.test.ts +++ b/packages/imperative/src/logger/__tests__/Logger.unit.test.ts @@ -93,11 +93,11 @@ describe("Logger tests", () => { logger.fatal("test"); // expect((logger as any).writeToLog).toBeCalled(); - expect((logger as any).logService.info).toBeCalled(); - expect((logger as any).logService.debug).toBeCalled(); - expect((logger as any).logService.warn).toBeCalled(); - expect((logger as any).logService.error).toBeCalled(); - expect((logger as any).logService.fatal).toBeCalled(); + expect((logger as any).logService.info).toHaveBeenCalled(); + expect((logger as any).logService.debug).toHaveBeenCalled(); + expect((logger as any).logService.warn).toHaveBeenCalled(); + expect((logger as any).logService.error).toHaveBeenCalled(); + expect((logger as any).logService.fatal).toHaveBeenCalled(); }); it("Should allow all service function to store message in memory", () => { @@ -174,11 +174,11 @@ describe("Logger tests", () => { logger.logError(error); - expect((logger as any).logService.trace).not.toBeCalled(); - expect((logger as any).logService.info).not.toBeCalled(); - expect((logger as any).logService.debug).toBeCalled(); + expect((logger as any).logService.trace).not.toHaveBeenCalled(); + expect((logger as any).logService.info).not.toHaveBeenCalled(); + expect((logger as any).logService.debug).toHaveBeenCalled(); expect((logger as any).logService.warn).not.toHaveBeenCalledTimes(1); - expect((logger as any).logService.fatal).not.toBeCalled(); + expect((logger as any).logService.fatal).not.toHaveBeenCalled(); expect((logger as any).logService.error).toHaveBeenCalledTimes(2); }); diff --git a/packages/imperative/src/logger/__tests__/LoggerConfigBuilder.unit.test.ts b/packages/imperative/src/logger/__tests__/LoggerConfigBuilder.unit.test.ts index 489577de15..8190706149 100644 --- a/packages/imperative/src/logger/__tests__/LoggerConfigBuilder.unit.test.ts +++ b/packages/imperative/src/logger/__tests__/LoggerConfigBuilder.unit.test.ts @@ -9,7 +9,7 @@ * */ -import { LoggerConfigBuilder } from "../../logger"; +import { LoggerConfigBuilder } from "../src/LoggerConfigBuilder"; import * as os from "os"; import * as path from "path"; @@ -67,7 +67,7 @@ describe("LoggerConfigBuilder tests", () => { it("Should use getDefaultFileName to append the Imperative CLI home to a passed-in file path", () => { const testFile = "test"; - const result = "/" + testFile + "/logs/" + testFile + ".log"; + const result = "/logs/" + testFile + ".log"; const builtPath = LoggerConfigBuilder.getDefaultFileName(testFile); expect(builtPath).toBe(result); }); diff --git a/packages/imperative/src/logger/__tests__/LoggerUtils.unit.test.ts b/packages/imperative/src/logger/__tests__/LoggerUtils.unit.test.ts index fe82898085..f1a6d8380f 100644 --- a/packages/imperative/src/logger/__tests__/LoggerUtils.unit.test.ts +++ b/packages/imperative/src/logger/__tests__/LoggerUtils.unit.test.ts @@ -10,7 +10,7 @@ */ import { EnvironmentalVariableSettings } from "../../imperative/src/env/EnvironmentalVariableSettings"; -import { LoggerUtils } from "../../logger"; +import { LoggerUtils } from "../src/LoggerUtils"; import { ImperativeConfig } from "../../utilities/src/ImperativeConfig"; describe("LoggerUtils tests", () => { diff --git a/packages/imperative/src/logger/__tests__/__snapshots__/LoggerConfigBuilder.unit.test.ts.snap b/packages/imperative/src/logger/__tests__/__snapshots__/LoggerConfigBuilder.unit.test.ts.snap index 4af7ca7c77..81b693e8ac 100644 --- a/packages/imperative/src/logger/__tests__/__snapshots__/LoggerConfigBuilder.unit.test.ts.snap +++ b/packages/imperative/src/logger/__tests__/__snapshots__/LoggerConfigBuilder.unit.test.ts.snap @@ -13,7 +13,7 @@ Object { }, "sampleFile": Object { "backups": 5, - "filename": "./someHome/sampleFile/logs/sampleFile.log", + "filename": "./someHome/logs/sampleFile.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -55,7 +55,7 @@ Object { "appenders": Object { "sampleFile": Object { "backups": 5, - "filename": "./someHome/sampleFile/logs/sampleFile.log", + "filename": "./someHome/logs/sampleFile.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -96,7 +96,7 @@ Object { }, "sampleFile1": Object { "backups": 5, - "filename": "./someHome/sampleFile1/logs/sampleFile1.log", + "filename": "./someHome/logs/sampleFile1.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", @@ -106,7 +106,7 @@ Object { }, "sampleFile2": Object { "backups": 5, - "filename": "./someHome/sampleFile2/logs/sampleFile2.log", + "filename": "./someHome/logs/sampleFile2.log", "layout": Object { "pattern": "[%d{yyyy/MM/dd} %d{hh:mm:ss.SSS}] [%p] %m", "type": "pattern", diff --git a/packages/imperative/src/logger/index.ts b/packages/imperative/src/logger/index.ts index d5f79edc41..9374b82aa8 100644 --- a/packages/imperative/src/logger/index.ts +++ b/packages/imperative/src/logger/index.ts @@ -14,5 +14,5 @@ export * from "./src/doc/ILog4jsAppender"; export * from "./src/doc/ILog4jsConfig"; export * from "./src/doc/ILog4jsLayout"; export * from "./src/Logger"; -export * from "./src/LoggerConfigBuilder"; -export * from "./src/LoggerUtils"; +// export * from "./src/LoggerConfigBuilder"; +// export * from "./src/LoggerUtils"; diff --git a/packages/imperative/src/logger/src/Logger.ts b/packages/imperative/src/logger/src/Logger.ts index ffa1011896..b3034d2199 100644 --- a/packages/imperative/src/logger/src/Logger.ts +++ b/packages/imperative/src/logger/src/Logger.ts @@ -353,8 +353,8 @@ export class Logger { try { const frame: StackTrace.StackFrame[] = StackTrace.parse(new Error()); let callerStackIndex = 1; - while (!frame[callerStackIndex].getFileName() || (frame[callerStackIndex].getFileName().indexOf(path.basename(__filename)) >= 0)) { - // go up the stack until we're outside of the BrightsideLogger file + while (!frame[callerStackIndex].getFileName() || frame[callerStackIndex].getFileName().indexOf(path.basename(__filename)) >= 0) { + // go up the stack until we're outside of the Zowe Logger file callerStackIndex += 1; } const filename = path.basename(frame[callerStackIndex].getFileName()); diff --git a/packages/imperative/src/logger/src/LoggerConfigBuilder.ts b/packages/imperative/src/logger/src/LoggerConfigBuilder.ts index 79171c5acf..a665032baa 100644 --- a/packages/imperative/src/logger/src/LoggerConfigBuilder.ts +++ b/packages/imperative/src/logger/src/LoggerConfigBuilder.ts @@ -10,7 +10,6 @@ */ import { IConfigLogging } from "./doc/IConfigLogging"; -import { IO } from "../../io"; import * as path from "path"; import * as os from "os"; @@ -25,8 +24,15 @@ export class LoggerConfigBuilder { public static readonly DEFAULT_BACKEND = "NONE"; public static readonly DEFAULT = "default"; - public static readonly DEFAULT_LOG_DIR = IO.FILE_DELIM; - public static readonly DEFAULT_LOG_FILE_DIR = "logs" + IO.FILE_DELIM; + /** + * @deprecated Use `DEFAULT_LOGS_DIR` instead. + */ + public static readonly DEFAULT_LOG_DIR = path.posix.sep; + /** + * @deprecated Use `DEFAULT_LOGS_DIR` instead. + */ + public static readonly DEFAULT_LOG_FILE_DIR = "logs" + path.posix.sep; + public static readonly DEFAULT_LOGS_DIR = "logs"; public static readonly DEFAULT_LOG_FILE_EXT = ".log"; public static readonly DEFAULT_LOG_FILE_MAX_SIZE = 10000000; // 10MB log size public static readonly DEFAULT_LOG_FILE_BACKUPS = 5; @@ -105,8 +111,7 @@ export class LoggerConfigBuilder { * @return {string} - the default file name for the log file */ public static getDefaultFileName(name: string) { - return LoggerConfigBuilder.DEFAULT_LOG_DIR + name + IO.FILE_DELIM + - LoggerConfigBuilder.DEFAULT_LOG_FILE_DIR + name + LoggerConfigBuilder.DEFAULT_LOG_FILE_EXT; + return path.posix.sep + path.posix.join(LoggerConfigBuilder.DEFAULT_LOGS_DIR, name + LoggerConfigBuilder.DEFAULT_LOG_FILE_EXT); } /** diff --git a/packages/imperative/src/messages/src/CoreMessages.ts b/packages/imperative/src/messages/src/CoreMessages.ts index 4077a78d2c..ba325e230a 100644 --- a/packages/imperative/src/messages/src/CoreMessages.ts +++ b/packages/imperative/src/messages/src/CoreMessages.ts @@ -33,320 +33,16 @@ export const unexpectedCommandPreparationError: IMessageDefinition = { message: "An unexpected command preparation error occurred:" }; -export const unableToLoadRequestedProfilesError: IMessageDefinition = { - message: "Command processing cannot continue: Unable to load requested or default profiles." -}; - -export const unexpectedProfileLoadError: IMessageDefinition = { - message: "An unexpected profile load error occurred:" -}; - -export const profileLoadError: IMessageDefinition = { - message: `Error loading {{type}} profile: {{profileName}}.\n\n` + - `Additional Details:\n\n` -}; - -export const unexpectedProfilesLoadError: IMessageDefinition = { - message: "An unexpected error occurred while loading requested profiles:\n" -}; - export const syntaxErrorHeader: IMessageDefinition = { message: `\nSyntax Error` }; -export const createProfilesCommandSummary: IMessageDefinition = { - message: `Create new configuration profiles`, -}; - -export const createProfilesCommandDesc: IMessageDefinition = { - message: `${createProfilesCommandSummary.message}.`, -}; - -export const createProfileCommandDesc: IMessageDefinition = { - message: `Create a {{type}} profile`, -}; - -export const createProfileOptionDesc: IMessageDefinition = { - message: `Specifies the name of the new {{type}} profile. ` + - `You can load this profile by using the name on commands that support the ` + - `"--{{type}}-profile" option.` -}; - -export const listProfileLoadedModulesOptionDesc: IMessageDefinition = { - message: `List {{type}} ` + - ` profiles that are loaded as part of normal command execution. ` + - `This will show you the default profiles being loaded.` -}; - -export const listProfileVerboseOptionDesc: IMessageDefinition = { - message: `List {{type}} ` + - ` profiles and their contents. ` + - `All profile details will be printed as part of command output.` -}; - -export const listProfileExample: IMessageDefinition = { - message: `List profiles of type {{type}}` -}; - -export const listProfileExampleShowContents: IMessageDefinition = { - message: `List profiles of type {{type}} and display their contents` -}; - -export const deleteProfileNameDesc: IMessageDefinition = { - message: `Specifies the name of the {{type}} ` + - ` profile to be deleted. ` + - `You can also load this profile by using the name on commands that support the ` + - `"--{{typeOption}}" option.` -}; - - -export const deleteProfileExample: IMessageDefinition = { - message: `Delete a {{type}} profile named {{name}}` -}; - - -export const validateProfileNameDesc: IMessageDefinition = { - message: `Specifies the name of the {{type}} ` + - ` profile to be validated. ` + - `If the --print-plan-only option is specified, then only a plan to validate the specified profile will be displayed.` -}; - - -export const selectProfileNameDesc: IMessageDefinition = { - message: `Specifies the name of the {{type}} ` + - ` - profile to be used with this command. ` + - `To see profiles that can be validated, issue the list action for this module. ` + - `You can also load this profile by using the name on commands that support the ` + - `"--{{typeOption}}" option.` -}; - - -export const createProfileOptionOverwriteDesc: IMessageDefinition = { - message: `Overwrite the {{type}} profile when a profile of the same name exists.` -}; - -export const createProfileDisableDefaultsDesc: IMessageDefinition = { - message: `Disable populating profile values of undefined properties with default values.` -}; - -export const deleteProfilesCommandSummary: IMessageDefinition = { - message: `Delete existing profiles` -}; - -export const deleteProfilesCommandDesc: IMessageDefinition = { - message: `${deleteProfilesCommandSummary.message}.` -}; - -export const deleteProfileForceOptionDesc: IMessageDefinition = { - message: `Force deletion of profile, and dependent profiles if specified. No prompt will be displayed before ` - + ` deletion occurs.` -}; - -export const deleteProfileActionDesc: IMessageDefinition = { - message: `Delete a {{type}} profile.` -}; - -export const deleteProfileCommandDesc: IMessageDefinition = { - message: `Delete a {{type}} profile.` + - ` You must specify a profile name to be deleted. To find a list of available profiles for deletion,` + - ` issue the profiles list command. By default, you will be prompted to confirm the profile removal.`, -}; - -export const deleteProfileDepsDesc: IMessageDefinition = { - message: `Set to true to delete all dependent profiles along with the {{type}} profile.` + - `If set to true, a list of dependent profiles will be shown along with a confirmation prompt before the ` + - `deletions occur. If set to false, only the {{type}} profile specified will be deleted.` -}; - -export const showDependenciesCommandDesc: IMessageDefinition = { - message: `View all profiles which may be used within a selected group.`, -}; - -export const listProfileCommandSummary: IMessageDefinition = { - message: `List existing profiles`, -}; - -export const listProfileCommandDesc: IMessageDefinition = { - message: `List profiles of the type {{type}}.`, -}; - -export const listProfilesFoundMessage: IMessageDefinition = { - message: `The following profiles were found of the type "{{type}}":`, -}; - -export const listProfilesNotFoundMessage: IMessageDefinition = { - message: `No profiles were found of the type "{{type}}".`, -}; - -export const validateProfileCommandSummary: IMessageDefinition = { - message: `Test the validity of a profile`, -}; - -export const validateProfileGroupDesc: IMessageDefinition = { - message: `Test the validity of your profiles.`, -}; -export const validateProfileCommandDesc: IMessageDefinition = { - message: `Test the validity of a {{type}} profile.`, -}; - -export const validateProfileOptionDesc: IMessageDefinition = { - message: `Validate the state of a group.`, -}; - -export const detailProfileCommandDesc: IMessageDefinition = { - message: `Show details of a profile of a selected type.`, -}; -export const updateProfileActionDesc: IMessageDefinition = { - message: `Update a {{type}} profile`, -}; - -export const updateProfileCommandSummary: IMessageDefinition = { - message: `Update existing profiles`, -}; - -export const updateProfileCommandDesc: IMessageDefinition = { - message: `Update a {{type}} profile. ` + - `You can update any property present within the profile configuration. The updated profile ` + - `will be printed so that you can review the result of the updates.`, -}; - -export const listGroupWithOnlyProfilesSummary: IMessageDefinition = { - message: `List the {{type}} profiles loaded` -}; - -export const listGroupWithOnlyProfilesDefinition: IMessageDefinition = { - message: `List the {{type}} profiles loaded.` -}; - -export const listGroupWithOnlyProfileDefaultDesc: IMessageDefinition = { - message: `Lists all known profiles for this command group. ` + - `When you issue a command that requires a profile or set of ` + - `profiles, said profiles are loaded by default (or according to override options on the command). You can use this ` + - `command to review your configured profiles, and verify your default profile set.` -}; - -export const listGroupWithOnlyProfileCommandSummary: IMessageDefinition = { - message: `List {{type}} loaded profiles` -}; - -export const listGroupWithOnlyProfileSetDesc: IMessageDefinition = { - message: `To set the default profiles, use the " ` + - `{{type}} ${Constants.DEFAULT_SET_GROUP} ${Constants.DEFAULT_SET_PROFILE_OBJECT}" command.` -}; - -export const setProfileActionSummary: IMessageDefinition = { - message: `Set which profiles are loaded by default` -}; - -export const setProfileActionDesc: IMessageDefinition = { - message: `${setProfileActionSummary.message}.` -}; - -export const setGroupWithOnlyProfilesSummary: IMessageDefinition = { - message: `Set the default - profiles for the {{type}} group` -}; - -export const setGroupWithOnlyProfilesCommandDesc: IMessageDefinition = { - message: `The {{type}} set ${Constants.DEFAULT_SET_PROFILE_OBJECT} command allows you to set the default profiles for ` + - `this command group. When a {{type}} command is issued and no profile override options are ` + - `specified, the default profiles for the command group are automatically loaded for the command based on the ` + - `commands profile requirements.` -}; - -export const setProfileOptionDesc: IMessageDefinition = { - message: `Specify a - profile for default usage within the {{type}} group. ` + - `When you issue commands within the {{type}} group without a profile specified as part of the command, the default ` + - `will be loaded instead.` -}; - -export const setProfileExample: IMessageDefinition = { - message: `Set the default profile for type {{type}} to the profile named '{{name}}'` -}; - -export const setGroupWithOnlyProfilesListDesc: IMessageDefinition = { - message: `To view the default profiles, use the " ` + - `{{type}} ${Constants.DEFAULT_LIST_GROUP} ${Constants.DEFAULT_LIST_PROFILE_OBJECT}" command.` -}; - - -export const profileCreatedSuccessfullyAndPath: IMessageDefinition = { - message: `Profile created successfully! Path:` -}; - -export const profileUpdatedSuccessfullyAndPath: IMessageDefinition = { - message: `Profile updated successfully! Path:` -}; - -export const profileReviewMessage: IMessageDefinition = { - message: "Review the created profile and edit if necessary using the profile update command." -}; - -export const profileCreateErrorHeader: IMessageDefinition = { - message: "Profile Create Error" -}; - -export const unableToCreateProfile: IMessageDefinition = { - message: "Unable to create the requested profile." -}; - -export const profileCreateErrorDetails: IMessageDefinition = { - message: "Error Details: {{errorDetails}}" -}; -export const profileNotDeletedMessage: IMessageDefinition = { - message: "No profiles were deleted." -}; - -export const profileDeletedSuccessfully: IMessageDefinition = { - message: "Successfully deleted the following profile(s): " -}; - -export const profileDeleteErrorHeader: IMessageDefinition = { - message: "Profile Deletion Error" -}; - -export const unableToDeleteProfile: IMessageDefinition = { - message: "Not all requested profiles could be deleted." -}; - -export const unableToFindProfile: IMessageDefinition = { - message: "Could not find or load the supplied profile name. Error details: " -}; - -export const profileDeleteErrorDetails: IMessageDefinition = { - message: "Error Details: {{errorDetails}}" -}; - -export const overroteProfileMessage: IMessageDefinition = { - message: "Overwrote existing profile for {{profileOption}}." -}; - -export const profileDesc: IMessageDefinition = { - message: `Configuration profiles are loaded based on the requirements ` + - `of the command:` -}; - -export const locateProfilesDesc: IMessageDefinition = { - message: `Configuration profiles are located and used by searching in the following order,` + - ` ending the search when a profile is found:` -}; - -export const profileCreatedSuccessfully: IMessageDefinition = { - message: `Profile created successfully.` -}; - -export const unexpectedProfileCreationError: IMessageDefinition = { - message: `An unexpected profile creation error occurred: \n{{unexpectedError}}` -}; - -export const unexpectedProfileUpdateError: IMessageDefinition = { - message: `An unexpected profile update error occurred: \n{{unexpectedError}}` +export const authCategorySummary: IMessageDefinition = { + message: `Connect to token-based authentication services` }; export const authCategoryDesc: IMessageDefinition = { - message: `Connect to token-based authentication services` + message: `${authCategorySummary.message}.` }; export const authLoginGroupSummary: IMessageDefinition = { @@ -358,7 +54,7 @@ export const authLoginGroupDesc: IMessageDefinition = { }; export const authLoginCommandDesc: IMessageDefinition = { - message: `Log in to {{type}} authentication service` + message: `Log in to {{type}} authentication service.` }; export const authLoginShowTokenDesc: IMessageDefinition = { @@ -374,9 +70,13 @@ export const authLogoutGroupDesc: IMessageDefinition = { }; export const authLogoutCommandDesc: IMessageDefinition = { - message: `Log out of {{type}} authentication service` + message: `Log out of {{type}} authentication service.` }; -export const autoInitCommandDesc: IMessageDefinition = { +export const autoInitCommandSummary: IMessageDefinition = { message: `Automatically generate a config from {{source}}` }; + +export const autoInitCommandDesc: IMessageDefinition = { + message: `${autoInitCommandSummary.message}.` +}; diff --git a/packages/imperative/src/operations/__tests__/__integration__/Operations.integration.spec.ts b/packages/imperative/src/operations/__tests__/__integration__/Operations.integration.spec.ts index be637f6505..36bbfc3a7c 100644 --- a/packages/imperative/src/operations/__tests__/__integration__/Operations.integration.spec.ts +++ b/packages/imperative/src/operations/__tests__/__integration__/Operations.integration.spec.ts @@ -10,14 +10,13 @@ */ /* eslint-disable jest/expect-expect */ +/* eslint-disable deprecation/deprecation */ import { TestOperations1 } from "../operation/TestOperations1"; import { TestOperations4 } from "../operation/TestOperations4"; - import { TestOperations3 } from "../operation/TestOperations3"; import { IOperationResult, Operation, Operations } from "../../index"; import { TestLogger } from "../../../../__tests__/src/TestLogger"; - const logger = TestLogger.getTestLogger(); class OperationTestConstants { diff --git a/packages/imperative/src/operations/__tests__/operation/TestOperations1.ts b/packages/imperative/src/operations/__tests__/operation/TestOperations1.ts index a56482a68f..7c182b322f 100644 --- a/packages/imperative/src/operations/__tests__/operation/TestOperations1.ts +++ b/packages/imperative/src/operations/__tests__/operation/TestOperations1.ts @@ -9,6 +9,7 @@ * */ +/* eslint-disable deprecation/deprecation */ import { TestSubOp1 } from "./subops/TestSubOp1"; import { TestSubOp2 } from "./subops/TestSubOp2"; import { TestSubOpNoUndo } from "./subops/TestSubOpNoUndo"; diff --git a/packages/imperative/src/operations/__tests__/operation/TestOperations2.ts b/packages/imperative/src/operations/__tests__/operation/TestOperations2.ts index 2734327281..b623306441 100644 --- a/packages/imperative/src/operations/__tests__/operation/TestOperations2.ts +++ b/packages/imperative/src/operations/__tests__/operation/TestOperations2.ts @@ -9,6 +9,7 @@ * */ +/* eslint-disable deprecation/deprecation */ import { TestSubOp4 } from "./subops/TestSubOp4"; import { TestSubOp5 } from "./subops/TestSubOp5"; import { Operations } from "../../../index"; diff --git a/packages/imperative/src/operations/__tests__/operation/TestOperations3.ts b/packages/imperative/src/operations/__tests__/operation/TestOperations3.ts index bf38287b1a..70dac2dde7 100644 --- a/packages/imperative/src/operations/__tests__/operation/TestOperations3.ts +++ b/packages/imperative/src/operations/__tests__/operation/TestOperations3.ts @@ -9,6 +9,7 @@ * */ +/* eslint-disable deprecation/deprecation */ import { TestSubOp6 } from "./subops/TestSubOp6"; import { TestOperations1 } from "./TestOperations1"; import { TestOperations2 } from "./TestOperations2"; diff --git a/packages/imperative/src/operations/__tests__/operation/TestOperations4.ts b/packages/imperative/src/operations/__tests__/operation/TestOperations4.ts index 0d8761e2ee..3d36d5109d 100644 --- a/packages/imperative/src/operations/__tests__/operation/TestOperations4.ts +++ b/packages/imperative/src/operations/__tests__/operation/TestOperations4.ts @@ -9,6 +9,7 @@ * */ +/* eslint-disable deprecation/deprecation */ import { TestOperations1 } from "./TestOperations1"; import { TestOperations2 } from "./TestOperations2"; import { TestSubOpFail } from "./subops/TestSubOpFail"; diff --git a/packages/imperative/src/operations/__tests__/operation/TestOperations5.ts b/packages/imperative/src/operations/__tests__/operation/TestOperations5.ts index 9568473ef6..ab64c9dc4f 100644 --- a/packages/imperative/src/operations/__tests__/operation/TestOperations5.ts +++ b/packages/imperative/src/operations/__tests__/operation/TestOperations5.ts @@ -9,6 +9,7 @@ * */ +/* eslint-disable deprecation/deprecation */ import { TestOperations1 } from "./TestOperations1"; import { TestSubOpDiverge } from "./subops/TestSubOpDiverge"; import { Operations } from "../../../index"; diff --git a/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp1.ts b/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp1.ts index bcd7e68d40..bd69833f90 100644 --- a/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp1.ts +++ b/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp1.ts @@ -9,6 +9,7 @@ * */ +/* eslint-disable deprecation/deprecation */ import { IOperationCompleted, IOperationUndoCompleted, Operation } from "../../../../index"; export class TestSubOp1 extends Operation { diff --git a/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp2.ts b/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp2.ts index fd91710248..e8bcf6287f 100644 --- a/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp2.ts +++ b/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp2.ts @@ -9,6 +9,7 @@ * */ +/* eslint-disable deprecation/deprecation */ import { IOperationCompleted, IOperationUndoCompleted, Operation } from "../../../../index"; export class TestSubOp2 extends Operation { diff --git a/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp4.ts b/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp4.ts index a6bba7be64..0bab8d3cff 100644 --- a/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp4.ts +++ b/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp4.ts @@ -9,6 +9,7 @@ * */ +/* eslint-disable deprecation/deprecation */ import { IOperationCompleted, IOperationUndoCompleted, Operation } from "../../../../index"; import { TestLogger } from "../../../../../__tests__/src/TestLogger"; diff --git a/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp5.ts b/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp5.ts index 07194c129c..a5de39dcf1 100644 --- a/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp5.ts +++ b/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp5.ts @@ -9,6 +9,7 @@ * */ +/* eslint-disable deprecation/deprecation */ import { IOperationCompleted, IOperationUndoCompleted, Operation } from "../../../../index"; import { TestLogger } from "../../../../../__tests__/src/TestLogger"; diff --git a/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp6.ts b/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp6.ts index 5a7e97c0ce..8ede9238a9 100644 --- a/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp6.ts +++ b/packages/imperative/src/operations/__tests__/operation/subops/TestSubOp6.ts @@ -9,6 +9,7 @@ * */ +/* eslint-disable deprecation/deprecation */ import { IOperationCompleted, IOperationUndoCompleted, Operation } from "../../../../index"; import { TestLogger } from "../../../../../__tests__/src/TestLogger"; diff --git a/packages/imperative/src/operations/__tests__/operation/subops/TestSubOpDiverge.ts b/packages/imperative/src/operations/__tests__/operation/subops/TestSubOpDiverge.ts index a5163a238d..d4cd259b55 100644 --- a/packages/imperative/src/operations/__tests__/operation/subops/TestSubOpDiverge.ts +++ b/packages/imperative/src/operations/__tests__/operation/subops/TestSubOpDiverge.ts @@ -9,6 +9,7 @@ * */ +/* eslint-disable deprecation/deprecation */ import { TestOperations2 } from "../TestOperations2"; import { IOperationCompleted, IOperationUndoCompleted, Operation } from "../../../../index"; import { TestLogger } from "../../../../../__tests__/src/TestLogger"; diff --git a/packages/imperative/src/operations/__tests__/operation/subops/TestSubOpFail.ts b/packages/imperative/src/operations/__tests__/operation/subops/TestSubOpFail.ts index 2806d2e80e..631f2e5e8a 100644 --- a/packages/imperative/src/operations/__tests__/operation/subops/TestSubOpFail.ts +++ b/packages/imperative/src/operations/__tests__/operation/subops/TestSubOpFail.ts @@ -9,6 +9,7 @@ * */ +/* eslint-disable deprecation/deprecation */ import { IOperationCompleted, IOperationUndoCompleted, Operation } from "../../../../index"; export class TestSubOpFail extends Operation { diff --git a/packages/imperative/src/operations/__tests__/operation/subops/TestSubOpNoUndo.ts b/packages/imperative/src/operations/__tests__/operation/subops/TestSubOpNoUndo.ts index 6ecf15e227..a35cbb37b8 100644 --- a/packages/imperative/src/operations/__tests__/operation/subops/TestSubOpNoUndo.ts +++ b/packages/imperative/src/operations/__tests__/operation/subops/TestSubOpNoUndo.ts @@ -9,6 +9,7 @@ * */ +/* eslint-disable deprecation/deprecation */ import { IOperationCompleted, IOperationUndoCompleted, Operation } from "../../../../index"; import { TestLogger } from "../../../../../__tests__/src/TestLogger"; diff --git a/packages/imperative/src/operations/src/Operation.ts b/packages/imperative/src/operations/src/Operation.ts index e616531aee..5f66df8652 100644 --- a/packages/imperative/src/operations/src/Operation.ts +++ b/packages/imperative/src/operations/src/Operation.ts @@ -9,6 +9,7 @@ * */ +/* eslint-disable deprecation/deprecation */ import { IOperationResult } from "./doc/IOperationResult"; import { TaskStage } from "./TaskStage"; import * as fs from "fs"; @@ -28,6 +29,9 @@ export type IOperationUndoCompleted = export type IOperationResultReady = (output: T, operationResults: IOperationResult) => void; +/** + * @deprecated + */ export abstract class Operation implements ITaskWithStatus { public static readonly NO_PARMS: any = null; @@ -185,7 +189,7 @@ export abstract class Operation implements ITaskWithStatus { operationUndoPossible: false, operationUndoFailed: false, operationUndoAttempted: false, - critical: (criticalOperation != null ? criticalOperation : false), + critical: criticalOperation != null ? criticalOperation : false, output: null, infoMessages: [], errorMessages: [] @@ -317,7 +321,7 @@ export abstract class Operation implements ITaskWithStatus { * @param {string} message: The result message you wish to append. */ set operationResultMessage(message: string) { - this.mOperationResult.resultMessage += (" " + message); + this.mOperationResult.resultMessage += " " + message; } /** diff --git a/packages/imperative/src/operations/src/Operations.ts b/packages/imperative/src/operations/src/Operations.ts index c95f30f6ef..937b232eda 100644 --- a/packages/imperative/src/operations/src/Operations.ts +++ b/packages/imperative/src/operations/src/Operations.ts @@ -9,12 +9,14 @@ * */ +/* eslint-disable deprecation/deprecation */ import { IOperationResultReady, Operation } from "./Operation"; import { IOperationResult } from "./doc/IOperationResult"; import { TextUtils } from "../../utilities"; import { TaskProgress } from "./TaskProgress"; /** + * @deprecated * The Operations class extends Operation and is used to create a 'string' of operations that must * be completed in serial order. * @@ -122,12 +124,12 @@ export abstract class Operations extends Operation { * @returns {number} percentComplete weighted against how many operations are complete */ public get percentComplete(): number { - const percentPerOp: number = (TaskProgress.ONE_HUNDRED_PERCENT / this.mOperationList.length); + const percentPerOp: number = TaskProgress.ONE_HUNDRED_PERCENT / this.mOperationList.length; const currentOpPercentComplete = this.mOperationList[this.mCurrentOperation].percentComplete == null ? 0 : this.mOperationList[this.mCurrentOperation].percentComplete; return Math.ceil(percentPerOp * this.mCurrentOperation + // how many operations completed so far (each 100%) - (percentPerOp * (currentOpPercentComplete / TaskProgress.ONE_HUNDRED_PERCENT))); + percentPerOp * (currentOpPercentComplete / TaskProgress.ONE_HUNDRED_PERCENT)); // what is the percent complete of the current operation in the list? weight that against number of ops } diff --git a/packages/imperative/src/operations/src/doc/IOperationResult.ts b/packages/imperative/src/operations/src/doc/IOperationResult.ts index 33baee79c9..d06ade3bae 100644 --- a/packages/imperative/src/operations/src/doc/IOperationResult.ts +++ b/packages/imperative/src/operations/src/doc/IOperationResult.ts @@ -9,6 +9,7 @@ * */ +/* eslint-disable deprecation/deprecation */ import { Operation } from "../Operation"; export interface IOperationResult { diff --git a/packages/imperative/src/profiles/__tests__/BasicProfileManager.constructor.unit.test.ts b/packages/imperative/src/profiles/__tests__/BasicProfileManager.constructor.unit.test.ts deleted file mode 100644 index 44732265b2..0000000000 --- a/packages/imperative/src/profiles/__tests__/BasicProfileManager.constructor.unit.test.ts +++ /dev/null @@ -1,251 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -jest.mock("../src/utils/ProfileIO"); -import { ImperativeError } from "../../error/src/ImperativeError"; -import { TestLogger } from "../../../__tests__/src/TestLogger"; -import { APPLE_PROFILE_TYPE, FRUIT_BASKET_BAD_DIR, FRUIT_BASKET_WORSE, MANGO_PROFILE_TYPE, ONLY_APPLE, TEST_PROFILE_ROOT_DIR } from "./TestConstants"; -import { BasicProfileManager } from "../src/BasicProfileManager"; -import { IProfileTypeConfiguration } from "../src/doc/config/IProfileTypeConfiguration"; - -// UnitTestUtils.replaceIt(); - -describe("Basic Profile Manager Constructor", () => { - it("should detect no parms when instantiating", () => { - let error; - try { - const prof = new BasicProfileManager(undefined); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect that the profile directory is undefined", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: undefined, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect that the profile directory is blank", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: " ", - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect that no type configuration is supplied", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: undefined, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain("An error occurred collecting all configurations from the profile root directory"); - }); - - it("should detect that the type configuration is an empty array", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: [], - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain("An error occurred collecting all configurations from the profile root directory"); - }); - - it("should detect if the type is undefined", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: undefined, - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect if the type is blank", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: " ", - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect that a type not found within the configurations", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: "bad_apple", - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain( - "Expect Error: Could not locate the profile type configuration for \"bad_apple\" within the input configuration list passed." - ); - }); - - it("should allow us to instantiate the cli profile manager", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - TestLogger.info("Profile Manager Created"); - } catch (e) { - error = e; - TestLogger.error(e); - } - expect(error).toBeUndefined(); - }); - - it("should detect that a schema definition document is attempting to overload 'type'", () => { - const copy: IProfileTypeConfiguration[] = JSON.parse(JSON.stringify(ONLY_APPLE)); - copy[0].schema.properties.type = {type: "boolean"}; - let caughtError; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - } catch (error) { - caughtError = error; - } - expect(caughtError).toBeUndefined(); - }); - - it("should detect that a schema definition document is attempting to overload 'name'", () => { - const copy: IProfileTypeConfiguration[] = JSON.parse(JSON.stringify(ONLY_APPLE)); - copy[0].schema.properties.name = {type: "boolean"}; - let caughtError; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - } catch (error) { - caughtError = error; - } - expect(caughtError).toBeUndefined(); - }); - - it("should detect that a schema definition document is attempting to overload 'dependencies'", () => { - const copy: IProfileTypeConfiguration[] = JSON.parse(JSON.stringify(ONLY_APPLE)); - copy[0].schema.properties.dependencies = {type: "boolean"}; - let caughtError; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - } catch (error) { - caughtError = error; - } - expect(caughtError).toBeUndefined(); - }); - - it("should allow instantiation if the meta doesn't have a default", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR + FRUIT_BASKET_WORSE, - type: MANGO_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - } - expect(error).toBeUndefined(); - }); - - it("should detect ill-formed meta profile configurations", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR + FRUIT_BASKET_BAD_DIR, - type: MANGO_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); -}); diff --git a/packages/imperative/src/profiles/__tests__/BasicProfileManager.delete.unit.test.ts b/packages/imperative/src/profiles/__tests__/BasicProfileManager.delete.unit.test.ts deleted file mode 100644 index 594859a70b..0000000000 --- a/packages/imperative/src/profiles/__tests__/BasicProfileManager.delete.unit.test.ts +++ /dev/null @@ -1,215 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - - -jest.mock("../src/utils/ProfileIO"); -import { BasicProfileManager } from "../src/BasicProfileManager"; -import { TestLogger } from "../../../__tests__/src/TestLogger"; -import { IProfileDeleted } from "../src/doc/response/IProfileDeleted"; -import { inspect } from "util"; -import { - APPLE_PROFILE_TYPE, - ONLY_APPLE, - STRAWBERRY_WITH_REQUIRED_APPLE_DEPENDENCY, - TEST_PROFILE_ROOT_DIR -} from "./TestConstants"; - - -describe("Basic Profile Manager Delete", () => { - it("should detect that no parms are supplied", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileDeleted; - try { - response = await prof.delete(undefined); - TestLogger.error(response.message); - TestLogger.error("Delete response - should not get here:\n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect the parms did not specify a name", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileDeleted; - try { - const parms = {name: "mulberry"}; - delete parms.name; - response = await prof.delete(parms); - TestLogger.error(response.message); - TestLogger.error("Delete response - should not get here:\n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should be able to detect the parms specified a blank name", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileDeleted; - try { - const parms = {name: " "}; - - response = await prof.delete(parms); - TestLogger.error(response.message); - TestLogger.error("Delete response - should not get here:\n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect there is no profile of the specified name to delete", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileDeleted; - try { - response = await prof.delete({name: "red_delicious"}); - TestLogger.error(response.message); - TestLogger.error("Delete response - should not get here:\n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should fail a delete where the profile to delete is marked as a dependency of another profile", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: STRAWBERRY_WITH_REQUIRED_APPLE_DEPENDENCY, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileDeleted; - try { - response = await prof.delete({name: "good_apple", rejectIfDependency: true}); - TestLogger.error(response.message); - TestLogger.error("Delete response - should not get here:\n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should be able to handle an error thrown by delete/unlink", async () => { - const prof: any = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - const profile = { - name: "mackintosh_error_apple" - }; - prof.loadProfile = jest.fn().mockReturnValue({profile}); - - let error; - let response: IProfileDeleted; - try { - response = await prof.delete(profile); - TestLogger.error(response.message); - TestLogger.error("Delete response - should not get here:\n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should be able to delete a profile", async () => { - const prof: any = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - const profile = { - name: "mackintosh_apple" - }; - prof.loadProfile = jest.fn().mockReturnValue({profile}); - - let error; - let response: IProfileDeleted; - try { - response = await prof.delete(profile); - TestLogger.info("Delete Full Response:\n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.error(error); - } - expect(error).toBeUndefined(); - expect(response.message).toMatchSnapshot(); - expect(response.path).toContain("mackintosh_apple.yaml"); - }); - - it("should detect that the profile to delete is marked as a dependency of another profile, but allow delete if specified", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: STRAWBERRY_WITH_REQUIRED_APPLE_DEPENDENCY, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileDeleted; - try { - response = await prof.delete({name: "good_apple", rejectIfDependency: false}); - TestLogger.error(response.message); - TestLogger.error("Delete response - should not get here:\n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeUndefined(); - expect(response.message).toMatchSnapshot(); - expect(response.path).toContain("good_apple.yaml"); - }); -}); diff --git a/packages/imperative/src/profiles/__tests__/BasicProfileManager.load.unit.test.ts b/packages/imperative/src/profiles/__tests__/BasicProfileManager.load.unit.test.ts deleted file mode 100644 index 5530004561..0000000000 --- a/packages/imperative/src/profiles/__tests__/BasicProfileManager.load.unit.test.ts +++ /dev/null @@ -1,488 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { TestLogger } from "../../../__tests__/src/TestLogger"; -import { inspect } from "util"; -import { IProfileLoaded } from "../../profiles/src/doc/response/IProfileLoaded"; -import { - APPLE_PROFILE_TYPE, - APPLE_TWO_REQ_DEP_BANANA_AND_STRAWBERRIES, - APPLE_TWO_REQ_DEP_BANANA_ONE_REQ_DEP_GRAPE, - APPLE_TWO_REQ_DEP_BANANA_ONE_REQ_DEP_GRAPE_ONE_REQ_DEP, - BLUEBERRY_PROFILE_TYPE, - ONLY_APPLE, - ONLY_BLUEBERRY, - ONLY_ORANGE, - ORANGE_PROFILE_TYPE, - STRAWBERRY_AND_APPLE_NO_DEP, - STRAWBERRY_PROFILE_TYPE, - STRAWBERRY_WITH_OPTIONAL_APPLE_DEPENDENCY, - STRAWBERRY_WITH_REQUIRED_APPLE_DEPENDENCY, - TEST_PROFILE_ROOT_DIR -} from "./TestConstants"; -import { BasicProfileManager } from "../src/BasicProfileManager"; - -jest.mock("../src/utils/ProfileIO"); - -describe("Basic Profile Manager Load", () => { - it("should detect missing parms", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - try { - const response = await prof.load(undefined); - TestLogger.error(response.message); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect parms with a missing profile name", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - try { - const response = await prof.load({}); - TestLogger.error(response.message); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should fail a load request if the profile is not found", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - try { - const response = await prof.load({name: "missing_apple"}); - } catch (e) { - error = e; - TestLogger.info(error.message); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should fail a load request if the profile loaded does not conform to the schema", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - try { - const response = await prof.load({name: "misshapen_apple"}); - } catch (e) { - error = e; - TestLogger.info(error.message); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should handle a read error", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - try { - const response = await prof.load({name: "throw_the_apple"}); - TestLogger.error(response.message); - } catch (e) { - error = e; - TestLogger.info(error.message); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should allow the load of a well formed profile", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileLoaded; - try { - response = await prof.load({name: "good_apple"}); - TestLogger.info(response.message); - } catch (e) { - error = e; - TestLogger.error(error.message); - } - expect(error).toBeUndefined(); - expect(response.message).toMatchSnapshot(); - expect(response.profile).toMatchSnapshot(); - expect(response.dependenciesLoaded).toBe(false); - expect(response.dependencyLoadResponses).toEqual([]); - expect(response.name).toBe("good_apple"); - expect(response.type).toBe(APPLE_PROFILE_TYPE); - }); - - it("should load the default if requested", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_BLUEBERRY, - type: BLUEBERRY_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileLoaded; - try { - response = await prof.load({loadDefault: true}); - TestLogger.info(response.message); - } catch (e) { - error = e; - TestLogger.info(error.message); - } - expect(error).toBeUndefined(); - expect(response.message).toMatchSnapshot(); - expect(response.profile).toMatchSnapshot(); - expect(response.dependenciesLoaded).toBe(false); - expect(response.dependencyLoadResponses).toEqual([]); - expect(response.name).toBe("sweet_blueberry"); - expect(response.type).toBe(BLUEBERRY_PROFILE_TYPE); - }); - - it("should fail if the default doesn't exist", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_ORANGE, - type: ORANGE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileLoaded; - try { - response = await prof.load({loadDefault: true}); - TestLogger.info(response.message); - } catch (e) { - error = e; - TestLogger.info(error.message); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should fail the request if no profile name is specified and default profile is set but not found", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_ORANGE, - type: ORANGE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - // Mock having a default profile set - prof.getDefaultProfileName = jest.fn(() => { - return "missing_orange"; - }); - - let error; - let response: IProfileLoaded; - try { - response = await prof.load({loadDefault: true, failNotFound: false}); - TestLogger.info(response.message); - } catch (e) { - error = e; - TestLogger.info(error.message); - } - expect(error).toBeDefined(); - expect(error.message).toContain("does not exist"); - expect(error.message).toMatchSnapshot(); - }); - - it("should not fail the request if 'fail not found' is false and the profile was not found", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_ORANGE, - type: ORANGE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileLoaded; - try { - response = await prof.load({loadDefault: true, failNotFound: false}); - TestLogger.info(response.message); - } catch (e) { - error = e; - TestLogger.info(error.message); - } - expect(error).toBeUndefined(); - expect(response.message).toMatchSnapshot(); - expect(response.profile).toBeUndefined(); - }); - - it("should load a profile with one dependency", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: STRAWBERRY_WITH_REQUIRED_APPLE_DEPENDENCY, - type: STRAWBERRY_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileLoaded; - try { - response = await prof.load({name: "sweet_strawberry"}); - TestLogger.info(response.message); - } catch (e) { - error = e; - TestLogger.error(error.message); - } - expect(error).toBeUndefined(); - expect(response).toMatchSnapshot(); - }); - - it("should load a profile with two dependencies", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: APPLE_TWO_REQ_DEP_BANANA_AND_STRAWBERRIES, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileLoaded; - try { - response = await prof.load({name: "apples_and_strawberries_and_bananas"}); - TestLogger.info(response.message); - } catch (e) { - error = e; - TestLogger.error(error.message); - } - expect(error).toBeUndefined(); - expect(response).toMatchSnapshot(); - }); - - it("should load a profile with two dependencies, one of which has it's own dependency", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: APPLE_TWO_REQ_DEP_BANANA_ONE_REQ_DEP_GRAPE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileLoaded; - try { - response = await prof.load({name: "apples_and_grapes_and_strawberries_and_bananas"}); - TestLogger.info(response.message); - TestLogger.info("Load response: \n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.error(error); - } - expect(error).toBeUndefined(); - expect(response).toMatchSnapshot(); - }); - - it("should fail a profile load with two dependencies, one of which has it's own dependency with an error", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: APPLE_TWO_REQ_DEP_BANANA_ONE_REQ_DEP_GRAPE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileLoaded; - try { - response = await prof.load({name: "apples_and_grapes_with_error_and_strawberries_and_bananas"}); - TestLogger.info(response.message); - TestLogger.info("Load response: \n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.error(error); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should fail a profile load with two dependencies, one of which has it's own dependency which is not found", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: APPLE_TWO_REQ_DEP_BANANA_ONE_REQ_DEP_GRAPE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileLoaded; - try { - response = await prof.load({name: "apples_and_grapes_not_found_and_strawberries_and_bananas"}); - TestLogger.info(response.message); - TestLogger.info("Load response: \n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.error(error); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should fail a profile load with two dependencies, one of which has it's own dependency that is circular", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: APPLE_TWO_REQ_DEP_BANANA_ONE_REQ_DEP_GRAPE_ONE_REQ_DEP, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileLoaded; - try { - response = await prof.load({name: "apple_has_circular"}); - TestLogger.error(response.message); - TestLogger.error("Load response: \n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should allow us to load all profiles for all types", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: STRAWBERRY_AND_APPLE_NO_DEP, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileLoaded[]; - try { - response = await prof.loadAll(); - TestLogger.info("Load response: \n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.error(error); - } - expect(error).toBeUndefined(); - expect(response).toMatchSnapshot(); - }); - - it("should allow us to load a profile with an optional dependency that is not specified", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: STRAWBERRY_WITH_OPTIONAL_APPLE_DEPENDENCY, - type: STRAWBERRY_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileLoaded; - try { - response = await prof.load({name: "strawberry_no_apple"}); - TestLogger.info("Load response: \n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.error(error); - } - expect(error).toBeUndefined(); - expect(response).toMatchSnapshot(); - }); - - it("should not allow us to load a profile with an optional dependency and the optional dependency doesn't exist", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: STRAWBERRY_WITH_OPTIONAL_APPLE_DEPENDENCY, - type: STRAWBERRY_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileLoaded; - try { - response = await prof.load({name: "strawberry_not_found_apple"}); - TestLogger.info("Load response: \n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.error(error); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should allow us to load a profile where an optional dependency doesn't exist (but fail not found is false)", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: STRAWBERRY_WITH_OPTIONAL_APPLE_DEPENDENCY, - type: STRAWBERRY_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileLoaded; - try { - response = await prof.load({name: "strawberry_not_found_apple", failNotFound: false}); - TestLogger.info("Load response: \n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.error(error); - } - expect(error).toBeUndefined(); - expect(response).toMatchSnapshot(); - }); - - it("should fail a load if the profile doesn't have the required dependencies listed when loaded", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: STRAWBERRY_WITH_REQUIRED_APPLE_DEPENDENCY, - type: STRAWBERRY_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileLoaded; - try { - response = await prof.load({name: "strawberry_no_apple"}); - TestLogger.info("Load response: \n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.error(error); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); -}); diff --git a/packages/imperative/src/profiles/__tests__/BasicProfileManager.merge.unit.test.ts b/packages/imperative/src/profiles/__tests__/BasicProfileManager.merge.unit.test.ts deleted file mode 100644 index 02d4f9c1a1..0000000000 --- a/packages/imperative/src/profiles/__tests__/BasicProfileManager.merge.unit.test.ts +++ /dev/null @@ -1,183 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -jest.mock("../src/utils/ProfileIO"); - -import { PROFILE_TYPE } from "../../../__tests__/src/packages/profiles/src/constants/BasicProfileManagerTestConstants"; -import { BasicProfileManager } from "../src/BasicProfileManager"; -import { - APPLE_PROFILE_TYPE, - GRAPE_PROFILE_TYPE, - ONLY_APPLE, - STRAWBERRY_WITH_REQUIRED_APPLE_DEPENDENCY, - TEST_PROFILE_ROOT_DIR -} from "./TestConstants"; -import { TestLogger } from "../../../__tests__/src/TestLogger"; -import { IProfile, ProfileIO } from "../"; -import { inspect } from "util"; - -// UnitTestUtils.replaceIt(); -const testLogger = TestLogger.getTestLogger(); -describe("Basic Profile Manager - Merge", () => { - it("Should be able to merge two simple profiles together, " + - "with the new profile taking precedence for same-name fields", () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - const profileA: IProfile = {type: APPLE_PROFILE_TYPE, name: "first", description: "first apple", age: 5}; - const profileB: IProfile = {type: APPLE_PROFILE_TYPE, name: "second", rotten: true}; - const merged = prof.mergeProfiles(profileA, profileB); - testLogger.info("Merged profile result: " + inspect(merged, {depth: null})); - expect(merged.name).toEqual(profileB.name); - expect(merged.rotten).toEqual(profileB.rotten); - expect(merged.description).toEqual(profileA.description); - expect(merged.age).toEqual(profileA.age); - }); - - it("should merge dependencies on profiles, while deleting duplicates", () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: STRAWBERRY_WITH_REQUIRED_APPLE_DEPENDENCY, - type: PROFILE_TYPE.STRAWBERRY, - logger: TestLogger.getTestLogger() - }); - - const profileA: IProfile = { - type: PROFILE_TYPE.STRAWBERRY, name: "first", - dependencies: [{type: APPLE_PROFILE_TYPE, name: "old_apple"}, {type: GRAPE_PROFILE_TYPE, name: "old_grape"}] - }; - const profileB: IProfile = { - type: PROFILE_TYPE.STRAWBERRY, - name: "second", - dependencies: [{type: APPLE_PROFILE_TYPE, name: "new_apple"}] - }; - const merged = prof.mergeProfiles(profileA, profileB); - testLogger.info("Merged profile result: " + inspect(merged, {depth: null})); - expect(merged.dependencies.length).toEqual(2); // should still have two dependencies - let appleDependency: any; - let grapeDependency: any; - for (const dependency of merged.dependencies) { - if (dependency.type === APPLE_PROFILE_TYPE) { - appleDependency = dependency; - } - else if (dependency.type === GRAPE_PROFILE_TYPE) { - grapeDependency = dependency; - } - } - expect(appleDependency).toBeDefined(); - expect(grapeDependency).toBeDefined(); - expect(appleDependency.name).toEqual(profileB.dependencies[0].name); - expect(grapeDependency.name).toEqual(profileA.dependencies[1].name); - }); - - it("should replace array type profile fields (other than dependencies) with newer versions of the array" + - "rather than merging them (merging them makes it impossible to specify new values when" + - "updating profiles via CLI) ", () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: STRAWBERRY_WITH_REQUIRED_APPLE_DEPENDENCY, - type: PROFILE_TYPE.STRAWBERRY, - logger: TestLogger.getTestLogger() - }); - const oldProfile: IProfile = { - type: PROFILE_TYPE.STRAWBERRY, name: "first", - myArrayVariable: ["old_value1", "oldValue2"], - // test that the array replacement still works on deeply nested fields - hasNestedArray: {hasNestedArray: {hasNestedArray: ["old_value1", "old_value2"]}} - }; - const newProfile: IProfile = { - type: PROFILE_TYPE.STRAWBERRY, - name: "first", - myArrayVariable: ["new_value1", "new_value2", "new_value3"], - hasNestedArray: {hasNestedArray: {hasNestedArray: ["new_value1", "new_value2", "new_value3", "new_value4"]}} - }; - const merged = prof.mergeProfiles(oldProfile, newProfile); - testLogger.info("Merged profile result: " + inspect(merged, {depth: null})); - expect(merged.myArrayVariable.length).toEqual(newProfile.myArrayVariable.length); - for (const oldValue of oldProfile.myArrayVariable) { - expect(merged.myArrayVariable.indexOf(oldValue)).toEqual(-1); - } - - for (const oldValue of oldProfile.hasNestedArray.hasNestedArray.hasNestedArray) { - expect(merged.hasNestedArray.hasNestedArray.hasNestedArray.indexOf(oldValue)).toEqual(-1); - } - expect(merged.hasNestedArray.hasNestedArray.hasNestedArray.length).toEqual(newProfile.hasNestedArray.hasNestedArray.hasNestedArray.length); - expect(merged.hasNestedArray).toEqual(newProfile.hasNestedArray); - }); - - it("should merge on update if \"merge\" is specified on the parms", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: [{ - type: PROFILE_TYPE.STRAWBERRY, - schema: { - type: "object", - title: "test profile for updating on merging", - description: "ditto", - properties: { - myArrayVariable: { - type: "array" - }, - hasNestedArray: { - type: "object" - } - } - } - }], - type: PROFILE_TYPE.STRAWBERRY, - logger: TestLogger.getTestLogger() - }); - const profileA = { - type: PROFILE_TYPE.STRAWBERRY, name: "first", - myArrayVariable: ["old_value1", "oldValue2"], - // test that the array replacement still works on deeply nested fields - hasNestedArray: {hasNestedArray: {hasNestedArray: ["old_value1", "old_value2"]}}, - }; - ProfileIO.writeProfile = jest.fn((path: string, profile: any) => { - // do nothing - }); - ProfileIO.exists = jest.fn((path: string) => { - return path.indexOf("meta") === -1 ? path : undefined; - }); - ProfileIO.readProfileFile = jest.fn((filePath: string, type: string) => { - if (type === PROFILE_TYPE.STRAWBERRY) { - return profileA; - } - else { - return { - type: "apple", - name: "thing" - }; - } - }); - const profileB: IProfile = { - myArrayVariable: ["new_value1", "new_value2", "new_value3"], - hasNestedArray: {hasNestedArray: {hasNestedArray: ["new_value1", "new_value2", "new_value3", "new_value4"]}}, - }; - const updateResult = await prof.update({name: "first", profile: profileB, merge: true}); - const merged = updateResult.profile; - testLogger.info("Merged profile result: " + inspect(merged, {depth: null})); - expect(merged.myArrayVariable.length).toEqual(profileB.myArrayVariable.length); - for (const oldValue of profileA.myArrayVariable) { - expect(merged.myArrayVariable.indexOf(oldValue)).toEqual(-1); - } - - for (const oldValue of profileA.hasNestedArray.hasNestedArray.hasNestedArray) { - expect(merged.hasNestedArray.hasNestedArray.hasNestedArray.indexOf(oldValue)).toEqual(-1); - } - expect(merged.hasNestedArray.hasNestedArray.hasNestedArray.length).toEqual(profileB.hasNestedArray.hasNestedArray.hasNestedArray.length); - expect(merged.hasNestedArray).toEqual(profileB.hasNestedArray); - }); -}); diff --git a/packages/imperative/src/profiles/__tests__/BasicProfileManager.save.unit.test.ts b/packages/imperative/src/profiles/__tests__/BasicProfileManager.save.unit.test.ts deleted file mode 100644 index 793ecf51bf..0000000000 --- a/packages/imperative/src/profiles/__tests__/BasicProfileManager.save.unit.test.ts +++ /dev/null @@ -1,625 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -jest.mock("../src/utils/ProfileIO"); -import { ImperativeError } from "../../error/src/ImperativeError"; -import { TestLogger } from "../../../__tests__/src/TestLogger"; -import { ISaveProfile } from "../src/doc/parms/ISaveProfile"; -import { inspect } from "util"; -import { IProfileSaved } from "../src/doc/response/IProfileSaved"; -import { - APPLE_BAN_UNKNOWN, - APPLE_PROFILE_TYPE, - APPLE_TWO_REQ_DEP_BANANA_ONE_REQ_DEP_GRAPE_ONE_REQ_DEP, - BANANA_PROFILE_TYPE, - MANGO_PROFILE_TYPE, - ONLY_APPLE, - ONLY_MANGO, - STRAWBERRY_PROFILE_TYPE, - STRAWBERRY_WITH_REQUIRED_APPLE_DEPENDENCY, - TEST_PROFILE_ROOT_DIR -} from "./TestConstants"; -import { BasicProfileManager } from "../src/BasicProfileManager"; - -const BAD_SAMPLE_SAVE_PARMS: ISaveProfile = { - name: "bad_apple", - type: "bad_apple", - profile: {} -}; - -const GOOD_SAMPLE_SAVE_PARMS: ISaveProfile = { - name: "apple", - type: STRAWBERRY_PROFILE_TYPE, - profile: {} -}; - -describe("Basic Profile Manager Save", () => { - it("should detect missing parameters", async () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - const response = await prof.save(undefined); - } catch (e) { - error = e; - TestLogger.info(e); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect missing profile", async () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - const parms = {name: "bad_apple", profile: {}}; - delete parms.profile; - const response = await prof.save(parms as any); - } catch (e) { - error = e; - TestLogger.info(e); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect a type mismatch when saving a profile", async () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: STRAWBERRY_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - const response = await prof.save(BAD_SAMPLE_SAVE_PARMS); - } catch (e) { - error = e; - TestLogger.info(e); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain( - "Expect Error: Could not locate the profile type configuration for \"strawberry\" within the input configuration list passed." - ); - }); - - it("should detect a blank name when creating a profile", async () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - const copy = JSON.parse(JSON.stringify({ - name: " ", - profile: {} - })); - const response = await prof.save(copy); - } catch (e) { - error = e; - TestLogger.info(e); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect a missing name when creating a profile", async () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - const copy = JSON.parse(JSON.stringify({ - profile: {} - })); - const response = await prof.save(copy); - } catch (e) { - error = e; - TestLogger.info(e); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect if the meta name was specified as the profile name", async () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - const copy = JSON.parse(JSON.stringify({ - name: APPLE_PROFILE_TYPE + "_meta", - profile: {} - })); - const response = await prof.save(copy); - } catch (e) { - error = e; - TestLogger.info(e); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect that the dependencies are not an array", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileSaved; - try { - const profile: any = {}; - profile.dependencies = {}; - response = await prof.save({name: "bad_apple", profile} as any); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect that the dependencies are present, but name is missing", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileSaved; - try { - const profile: any = {}; - profile.dependencies = [{type: STRAWBERRY_PROFILE_TYPE}]; - response = await prof.save({name: "bad_apple", profile} as any); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect that the dependencies are present, but type is missing", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileSaved; - try { - const profile: any = {}; - profile.dependencies = [{name: "bad_strawberry"}]; - response = await prof.save({name: "bad_apple", profile} as any); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect that a profile requires a dependency of a certain type", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: STRAWBERRY_WITH_REQUIRED_APPLE_DEPENDENCY, - type: STRAWBERRY_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileSaved; - try { - const profile: any = {description: "A bunch of rotten strawberries", amount: 30}; - response = await prof.save({name: "bad_strawberry", profile} as any); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect all missing required fields on the schema", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: STRAWBERRY_WITH_REQUIRED_APPLE_DEPENDENCY, - type: STRAWBERRY_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileSaved; - try { - const profile: any = { - dependencies: [{type: APPLE_PROFILE_TYPE, name: "bad_apple"}] - }; - response = await prof.save({name: "bad_strawberry", profile} as any); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect a type mismatch from the schema for strings", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileSaved; - try { - const profile: any = {description: true, rotten: true, age: 100}; - response = await prof.save({name: "bad_apple", profile} as any); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect a type mismatch from the schema for booleans", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileSaved; - try { - const profile: any = {description: "A nasty apple", rotten: "yes", age: 100}; - response = await prof.save({name: "bad_apple", profile} as any); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should fail a save request if the file already exists and overwrite is false", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - try { - const profile: any = {description: "A nasty apple", rotten: true, age: 100}; - const saveResponse = await prof.save({ - name: "old_apple", - profile, - overwrite: false - } as any); - } catch (e) { - error = e; - TestLogger.info(e.message); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should fail a save request if an error is thrown by write file", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - try { - const profile: any = {description: "A nasty apple", rotten: true, age: 100}; - const saveResponse = await prof.save({ - name: "throw_the_apple", - profile, - overwrite: true - } as any); - } catch (e) { - error = e; - TestLogger.info(e.message); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should fail a save request if there is an error writing the meta file", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_MANGO, - type: MANGO_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - try { - const profile: any = {description: "A nasty mango", peeled: true}; - const saveResponse = await prof.save({ - name: "bad_mango", - profile, - overwrite: true, - updateDefault: true - } as any); - } catch (e) { - error = e; - TestLogger.info(e.message); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should allow us to save a well-formed profile", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let saveResponse: IProfileSaved; - try { - const profile: any = {description: "A tasty apple", rotten: false, age: 1}; - saveResponse = await prof.save({ - name: "good_apple", - profile, - overwrite: true - } as any); - } catch (e) { - error = e; - TestLogger.info(e.message); - } - expect(error).toBeUndefined(); - expect(saveResponse.message).toContain('Profile ("good_apple" of type "apple") successfully written:'); - expect(saveResponse.profile).toMatchSnapshot(); - }); - - it("should allow us to save a profile with a dependency", async () => { - const copy = JSON.parse(JSON.stringify(STRAWBERRY_WITH_REQUIRED_APPLE_DEPENDENCY)); - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: copy, - type: STRAWBERRY_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let saveResponse: IProfileSaved; - try { - const strawberry: any = { - type: STRAWBERRY_PROFILE_TYPE, - amount: 10000, - description: "Strawberries covered in chocolate.", - dependencies: [ - { - type: APPLE_PROFILE_TYPE, - name: "tasty_apples" - } - ] - }; - saveResponse = await prof.save({ - name: "chocolate_covered", - profile: strawberry, - overwrite: true - } as any); - } catch (e) { - error = e; - } - expect(error).toBeUndefined(); - expect(saveResponse.message).toContain('Profile ("chocolate_covered" of type "strawberry") successfully written:'); - expect(saveResponse.profile).toMatchSnapshot(); - }); - - it("should not allow us to overwrite a profile if overwrite false (or not specified)", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let saveResponse: IProfileSaved; - try { - const profile: any = {description: "A tasty apple", rotten: false, age: 1}; - saveResponse = await prof.save({ - name: "good_apple", - profile, - } as any); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should not allow a save with a circular dependency", async () => { - const copy = JSON.parse(JSON.stringify(APPLE_TWO_REQ_DEP_BANANA_ONE_REQ_DEP_GRAPE_ONE_REQ_DEP)); - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: copy, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileSaved; - try { - response = await prof.save({ - name: "apple_with_two_req_dep_circular", - type: APPLE_PROFILE_TYPE, - profile: { - age: 1000, - description: "An old apple", - rotten: true, - dependencies: [ - { - type: STRAWBERRY_PROFILE_TYPE, - name: "chocolate_covered" - }, - { - type: BANANA_PROFILE_TYPE, - name: "banana_with_grape_dep" - } - ] - }, - overwrite: true - }); - TestLogger.error(response.message); - TestLogger.error("Save response: \n" + inspect(response, {depth: null})); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should not allow a save with no contents", async () => { - const copy = JSON.parse(JSON.stringify(ONLY_APPLE)); - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: copy, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileSaved; - try { - response = await prof.save({ - name: "no_apple_core", - profile: {}, - overwrite: true - } as any); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should not allow us to save a profile that lists dependencies of types that were not defined", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let saveResponse: IProfileSaved; - try { - const profile: any = { - description: "A tasty apple", - rotten: false, - age: 1, - dependencies: [{name: "bad_pear", type: "pear"}] - }; - saveResponse = await prof.save({ - name: "good_apple", - profile, - overwrite: true - } as any); - } catch (e) { - error = e; - TestLogger.info(e.message); - } - expect(error).toBeDefined(); - expect(error.message).toContain("Could not save the profile, because one or more dependencies is invalid or does not exist."); - expect(error.message).toContain( - "Load Error Details: Expect Error: Could not locate the profile type " + - "configuration for \"pear\" within the input configuration list passed." - ); - }); - - it("should fail a save request if a profile has more properties than defined on the schema", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: APPLE_BAN_UNKNOWN, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let saveResponse: IProfileSaved; - try { - const profile: any = { - description: "A tasty apple", - rotten: false, - age: 1, - seedless: false - }; - saveResponse = await prof.save({ - name: "tasty_apple", - profile, - overwrite: true - } as any); - } catch (e) { - error = e; - TestLogger.info(e.message); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); -}); diff --git a/packages/imperative/src/profiles/__tests__/BasicProfileManager.unit.test.ts b/packages/imperative/src/profiles/__tests__/BasicProfileManager.unit.test.ts deleted file mode 100644 index 8c14a19447..0000000000 --- a/packages/imperative/src/profiles/__tests__/BasicProfileManager.unit.test.ts +++ /dev/null @@ -1,387 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -jest.mock("../src/utils/ProfileIO"); -import { ImperativeError } from "../../error/src/ImperativeError"; -import { TestLogger } from "../../../__tests__/src/TestLogger"; -import { IProfileLoaded } from "../../profiles/src/doc/response/IProfileLoaded"; -import { - APPLE_PROFILE_TYPE, - APPLE_TWO_REQ_DEP_BANANA_AND_STRAWBERRIES, - APPLE_TWO_REQ_DEP_BANANA_ONE_REQ_DEP_GRAPE, - BLUEBERRY_PROFILE_TYPE, - FRUIT_BASKET_DIR, - ONLY_APPLE, - ONLY_BLUEBERRY, - STRAWBERRY_AND_APPLE_NO_DEP, - TEST_PROFILE_ROOT_DIR -} from "./TestConstants"; -import { BasicProfileManager } from "../src/BasicProfileManager"; -// UnitTestUtils.replaceIt(); - -describe("Basic Profile Manager", () => { - it("should detect no parms when instantiating", () => { - let error; - try { - const prof = new BasicProfileManager(undefined); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect that the profile directory is undefined", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: undefined, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect that the profile directory is blank", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: " ", - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect that no type configuration is supplied", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: undefined, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain("An error occurred collecting all configurations from the profile root directory"); - }); - - it("should detect that the type configuration is an empty array", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: [], - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain("An error occurred collecting all configurations from the profile root directory"); - }); - - it("should detect if the type is undefined", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: undefined, - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect if the type is blank", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: " ", - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect that a type not found within the configurations", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: "bad_apple", - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain( - "Expect Error: Could not locate the profile type configuration for \"bad_apple\" within the input configuration list passed." - ); - }); - - it("should allow us to instantiate the cli profile manager", () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - TestLogger.info("Profile Manager Created"); - } catch (e) { - error = e; - TestLogger.error(e); - } - expect(error).toBeUndefined(); - }); - - it("should load all profiles", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: STRAWBERRY_AND_APPLE_NO_DEP, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let responses: IProfileLoaded[]; - try { - responses = await prof.loadAll(); - } catch (e) { - error = e; - TestLogger.error(e); - } - expect(error).toBeUndefined(); - expect(responses).toMatchSnapshot(); - }); - - it("should detect ill formed profiles during a load all", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: APPLE_TWO_REQ_DEP_BANANA_AND_STRAWBERRIES, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let responses: IProfileLoaded[]; - try { - responses = await prof.loadAll(); - } catch (e) { - error = e; - TestLogger.error(e); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should initialize the environment", async () => { - const responses = await BasicProfileManager.initialize({ - configuration: APPLE_TWO_REQ_DEP_BANANA_ONE_REQ_DEP_GRAPE, - profileRootDirectory: TEST_PROFILE_ROOT_DIR - }); - - expect(responses).toBeDefined(); - expect(responses).toMatchSnapshot(); - }); - - it("should detect missing parms on initialize", async () => { - let error; - try { - const responses = await BasicProfileManager.initialize(undefined); - } catch (e) { - error = e; - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect missing configuration on initialize", async () => { - let error; - try { - const parms = { - configuration: undefined as any, - profileRootDirectory: TEST_PROFILE_ROOT_DIR - }; - const responses = await BasicProfileManager.initialize(parms); - } catch (e) { - error = e; - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect missing profile directory on initialize", async () => { - let error; - try { - const parms = { - configuration: APPLE_TWO_REQ_DEP_BANANA_ONE_REQ_DEP_GRAPE, - profileRootDirectory: undefined as any - }; - const responses = await BasicProfileManager.initialize(parms); - } catch (e) { - error = e; - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect blank profile directory on initialize", async () => { - let error; - try { - const parms = { - configuration: APPLE_TWO_REQ_DEP_BANANA_ONE_REQ_DEP_GRAPE, - profileRootDirectory: " " - }; - const responses = await BasicProfileManager.initialize(parms); - } catch (e) { - error = e; - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should create an instance and read all configurations from the meta files", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR + FRUIT_BASKET_DIR, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - expect(prof.configurations).toMatchSnapshot(); - }); - - it("should fail a create if no configurations and passed and none can be read from disk", async () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - } catch (e) { - error = e; - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect that the configuration passed is not an array", async () => { - const init: any = { - configuration: [], - profileRootDirectory: TEST_PROFILE_ROOT_DIR + FRUIT_BASKET_DIR - }; - init.configuration = {}; - let error; - try { - const responses = await BasicProfileManager.initialize(init); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should only initialize types not already defined in the environment", async () => { - const responses = await BasicProfileManager.initialize({ - configuration: APPLE_TWO_REQ_DEP_BANANA_ONE_REQ_DEP_GRAPE, - profileRootDirectory: TEST_PROFILE_ROOT_DIR + FRUIT_BASKET_DIR - }); - expect(responses).toBeDefined(); - expect(responses).toMatchSnapshot(); - }); - - it("should allow a re-initialize of the environment", async () => { - const responses = await BasicProfileManager.initialize({ - configuration: APPLE_TWO_REQ_DEP_BANANA_ONE_REQ_DEP_GRAPE, - profileRootDirectory: TEST_PROFILE_ROOT_DIR + FRUIT_BASKET_DIR, - reinitialize: true - }); - expect(responses).toBeDefined(); - expect(responses).toMatchSnapshot(); - }); - - it("should allow us to set the default in the meta profile", () => { - let error; - let response; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_BLUEBERRY, - type: BLUEBERRY_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - response = prof.setDefault("tart_blueberry"); - } catch (e) { - error = e; - TestLogger.error(e); - } - expect(error).toBeUndefined(); - expect(response).toMatchSnapshot(); - }); - - it("should fail a request to set the default if the profile is not found", () => { - let error; - let response; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_BLUEBERRY, - type: BLUEBERRY_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - response = prof.setDefault("bad_blueberry"); - } catch (e) { - error = e; - TestLogger.info(e); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - expect(response).toBeUndefined(); - }); -}); diff --git a/packages/imperative/src/profiles/__tests__/BasicProfileManager.update.unit.test.ts b/packages/imperative/src/profiles/__tests__/BasicProfileManager.update.unit.test.ts deleted file mode 100644 index 9071658896..0000000000 --- a/packages/imperative/src/profiles/__tests__/BasicProfileManager.update.unit.test.ts +++ /dev/null @@ -1,83 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { BasicProfileManager } from "../src/BasicProfileManager"; -import { APPLE_PROFILE_TYPE, ONLY_APPLE, TEST_PROFILE_ROOT_DIR } from "./TestConstants"; -import { TestLogger } from "../../../__tests__/src/TestLogger"; -import { IProfileUpdated } from "../src/doc/response/IProfileUpdated"; - -jest.mock("../src/utils/ProfileIO"); - - -describe("Basic Profile Manager Update", () => { - it("should detect missing parameters", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileUpdated; - try { - response = await prof.update(undefined); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect missing name parameter", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileUpdated; - try { - response = await prof.update({}); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); - - it("should allow us to update a profile", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileUpdated; - try { - response = await prof.update({ - name: "good_apple", - profile: { - rotten: false, - description: "Getting older, but still good.", age: 2 - } - } as any); - } catch (e) { - error = e; - } - expect(error).toBeUndefined(); - expect(response.message).toMatchSnapshot(); - }); -}); diff --git a/packages/imperative/src/profiles/__tests__/BasicProfileManager.validate.unit.test.ts b/packages/imperative/src/profiles/__tests__/BasicProfileManager.validate.unit.test.ts deleted file mode 100644 index 9d4b548882..0000000000 --- a/packages/imperative/src/profiles/__tests__/BasicProfileManager.validate.unit.test.ts +++ /dev/null @@ -1,308 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { BasicProfileManager } from "../src/BasicProfileManager"; -import { TestLogger } from "../../../__tests__/src/TestLogger"; -import { IProfileValidated } from "../src/doc/response/IProfileValidated"; -import { - APPLE_PROFILE_TYPE, - ONLY_APPLE, - STRAWBERRY_PROFILE_TYPE, - STRAWBERRY_WITH_REQUIRED_APPLE_DEPENDENCY, - TEST_PROFILE_ROOT_DIR -} from "./TestConstants"; -import { ImperativeError } from "../../error/src/ImperativeError"; - -jest.mock("../src/utils/ProfileIO"); - -describe("Basic Profile Manager Validate", () => { - it("should detect undefined parms", async () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - const response = await prof.validate(undefined); - } catch (e) { - error = e; - TestLogger.info(e); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect a type mismatch", async () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: STRAWBERRY_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - const response = await prof.validate({profile: {}} as any); - } catch (e) { - error = e; - TestLogger.info(e); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain( - "Expect Error: Could not locate the profile type configuration for \"strawberry\" within the input configuration list passed." - ); - }); - - it("should detect a that we are attempting to use the meta name", async () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - const copy = JSON.parse(JSON.stringify({ - name: APPLE_PROFILE_TYPE + "_meta", - profile: {} - })); - const response = await prof.validate(copy); - } catch (e) { - error = e; - TestLogger.info(e); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect a missing profile name", async () => { - let error; - try { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - const response = await prof.validate({profile: {}} as any); - } catch (e) { - error = e; - TestLogger.info(e); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect that the dependencies are not an array", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - try { - const profile: any = {}; - profile.dependencies = {}; - const response = await prof.validate({name: "bad_apple", profile}); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should detect that the dependencies are present, but name is missing", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - try { - const profile: any = {}; - profile.dependencies = [{type: STRAWBERRY_PROFILE_TYPE}]; - const response = await prof.validate({name: "bad_apple", profile}); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should be able to detect that the dependencies are present, but type is missing", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - try { - const profile: any = {}; - profile.dependencies = [{name: "bad_strawberry"}]; - const response = await prof.validate({name: "bad_apple", profile}); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should be able to detect that a profile requires a dependency of a certain type", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: STRAWBERRY_WITH_REQUIRED_APPLE_DEPENDENCY, - type: STRAWBERRY_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - try { - const profile: any = {description: "A bunch of rotten strawberries", amount: 30}; - const response = await prof.validate({name: "bad_strawberry", profile}); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should be able to detect all missing required fields on the schema", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: STRAWBERRY_WITH_REQUIRED_APPLE_DEPENDENCY, - type: STRAWBERRY_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - try { - const profile: any = { - - dependencies: [{type: APPLE_PROFILE_TYPE, name: "bad_apple"}] - }; - const response = await prof.validate({name: "bad_strawberry", profile}); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should be able to detect a type mismatch from the schema for strings", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - try { - const profile: any = {description: true, rotten: true, age: 100}; - const response = await prof.validate({name: "bad_apple", profile}); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should be able to detect a type mismatch from the schema for booleans", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - try { - const profile: any = {description: "A nasty apple", rotten: "yes", age: 100}; - const response = await prof.validate({name: "bad_apple", profile}); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toMatchSnapshot(); - }); - - it("should validate a well formed profile successfully", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileValidated; - try { - const profile: any = {description: "A tasty apple", rotten: false, age: 1}; - response = await prof.validate({name: "good_apple", profile}); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeUndefined(); - expect(response.message).toMatchSnapshot(); - }); - - it("should fail a save request if a profile has more properties than defined on the schema", async () => { - const prof = new BasicProfileManager({ - profileRootDirectory: TEST_PROFILE_ROOT_DIR, - typeConfigurations: ONLY_APPLE, - type: APPLE_PROFILE_TYPE, - logger: TestLogger.getTestLogger() - }); - - let error; - let response: IProfileValidated; - try { - const profile: any = { - description: "A tasty apple", - rotten: false, - age: 1, - seedless: false - }; - response = await prof.validate({name: "good_apple", profile, strict: true}); - } catch (e) { - error = e; - TestLogger.info(error); - } - expect(error).toBeDefined(); - expect(error.message).toMatchSnapshot(); - }); -}); diff --git a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.constructor.unit.test.ts.snap b/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.constructor.unit.test.ts.snap deleted file mode 100644 index 5676ecfca2..0000000000 --- a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.constructor.unit.test.ts.snap +++ /dev/null @@ -1,13 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Basic Profile Manager Constructor should detect if the type is blank 1`] = `"Expect Error: No profile type supplied on the profile manager parameters."`; - -exports[`Basic Profile Manager Constructor should detect if the type is undefined 1`] = `"Expect Error: No profile type supplied on the profile manager parameters."`; - -exports[`Basic Profile Manager Constructor should detect ill-formed meta profile configurations 1`] = `"An error occurred collecting all configurations from the profile root directory \\"__tests__/__results__/test_profiles/root/dir//FRUIT_BAD_BASKET/\\". Please supply the configurations on the profile manager constructor parameters OR initialize the profile manager environment. Details: Expect Error: A meta profile of type \\"mango\\", does NOT supply a configuration."`; - -exports[`Basic Profile Manager Constructor should detect no parms when instantiating 1`] = `"Expect Error: Profile Manager input parms not supplied."`; - -exports[`Basic Profile Manager Constructor should detect that the profile directory is blank 1`] = `"Expect Error: No profile root directory supplied on the profile manager parameters"`; - -exports[`Basic Profile Manager Constructor should detect that the profile directory is undefined 1`] = `"Expect Error: No profile root directory supplied on the profile manager parameters"`; diff --git a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.delete.unit.test.ts.snap b/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.delete.unit.test.ts.snap deleted file mode 100644 index 4836b56f89..0000000000 --- a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.delete.unit.test.ts.snap +++ /dev/null @@ -1,20 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Basic Profile Manager Delete should detect there is no profile of the specified name to delete 1`] = `"Profile \\"red_delicious\\" of type \\"apple\\" does not exist."`; - -exports[`Basic Profile Manager Delete should be able to delete a profile 1`] = `"Profile \\"mackintosh_apple\\" of type \\"apple\\" deleted successfully."`; - -exports[`Basic Profile Manager Delete should be able to detect the parms specified a blank name 1`] = `"Expect Error: A delete was requested for profile type \\"apple\\", but the name specified is undefined or blank."`; - -exports[`Basic Profile Manager Delete should be able to handle an error thrown by delete/unlink 1`] = `"IO ERROR DELETING THE APPLE"`; - -exports[`Basic Profile Manager Delete should detect that no parms are supplied 1`] = `"Expect Error: A delete was requested for profile type \\"apple\\", but no parameters were specified."`; - -exports[`Basic Profile Manager Delete should detect that the profile to delete is marked as a dependency of another profile, but allow delete if specified 1`] = `"Profile \\"good_apple\\" of type \\"apple\\" deleted successfully."`; - -exports[`Basic Profile Manager Delete should detect the parms did not specify a name 1`] = `"Expect Error: A delete was requested for profile type \\"apple\\", but the name specified is undefined or blank."`; - -exports[`Basic Profile Manager Delete should fail a delete where the profile to delete is marked as a dependency of another profile 1`] = ` -"The profile specified for deletion (\\"good_apple\\" of type \\"apple\\") is marked as a dependency for profiles: -Name: \\"strawberry_and_apple\\" Type: \\"strawberry\\"" -`; diff --git a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.load.unit.test.ts.snap b/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.load.unit.test.ts.snap deleted file mode 100644 index 0bca82d962..0000000000 --- a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.load.unit.test.ts.snap +++ /dev/null @@ -1,339 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Basic Profile Manager Load should allow the load of a well formed profile 1`] = `"Profile \\"good_apple\\" of type \\"apple\\" loaded successfully."`; - -exports[`Basic Profile Manager Load should allow the load of a well formed profile 2`] = ` -Object { - "age": 1, - "description": "A tasty apple", - "rotten": false, -} -`; - -exports[`Basic Profile Manager Load should allow us to load a profile where an optional dependency doesn't exist (but fail not found is false) 1`] = ` -Object { - "dependenciesLoaded": true, - "dependencyLoadResponses": Array [ - Object { - "dependenciesLoaded": false, - "dependencyLoadResponses": Array [], - "failNotFound": false, - "message": "Profile \\"missing_apple\\" of type \\"apple\\" was not found, but the request indicated to ignore \\"not found\\" errors. The profile returned is undefined.", - "name": "missing_apple", - "type": "apple", - }, - ], - "failNotFound": false, - "message": "Profile \\"strawberry_not_found_apple\\" of type \\"strawberry\\" loaded successfully.", - "name": "strawberry_not_found_apple", - "profile": Object { - "amount": 1000, - "dependencies": Array [ - Object { - "name": "missing_apple", - "type": "apple", - }, - ], - "description": "Tasty", - }, - "type": "strawberry", -} -`; - -exports[`Basic Profile Manager Load should allow us to load a profile with an optional dependency that is not specified 1`] = ` -Object { - "dependenciesLoaded": false, - "dependencyLoadResponses": Array [], - "failNotFound": true, - "message": "Profile \\"strawberry_no_apple\\" of type \\"strawberry\\" loaded successfully.", - "name": "strawberry_no_apple", - "profile": Object { - "amount": 1000, - "description": "Tasty", - }, - "type": "strawberry", -} -`; - -exports[`Basic Profile Manager Load should allow us to load all profiles for all types 1`] = ` -Array [ - Object { - "dependenciesLoaded": false, - "dependencyLoadResponses": Array [], - "failNotFound": true, - "message": "Profile \\"good_apple\\" of type \\"apple\\" loaded successfully.", - "name": "good_apple", - "profile": Object { - "age": 1, - "description": "A tasty apple", - "rotten": false, - }, - "type": "apple", - }, - Object { - "dependenciesLoaded": false, - "dependencyLoadResponses": Array [], - "failNotFound": true, - "message": "Profile \\"tasty_apples\\" of type \\"apple\\" loaded successfully.", - "name": "tasty_apples", - "profile": Object { - "age": 1, - "description": "tasty", - "rotten": false, - }, - "type": "apple", - }, - Object { - "dependenciesLoaded": false, - "dependencyLoadResponses": Array [], - "failNotFound": true, - "message": "Profile \\"strawberry_and_apple\\" of type \\"strawberry\\" loaded successfully.", - "name": "strawberry_and_apple", - "profile": Object { - "amount": 1000, - "dependencies": Array [ - Object { - "name": "good_apple", - "type": "apple", - }, - ], - "description": "Tasty", - }, - "type": "strawberry", - }, -] -`; - -exports[`Basic Profile Manager Load should detect missing parms 1`] = `"Expect Error: Profile load requested for type \\"apple\\", but no parameters supplied."`; - -exports[`Basic Profile Manager Load should detect parms with a missing profile name 1`] = `"Expect Error: A profile load was requested for type \\"apple\\", but no profile name was specified."`; - -exports[`Basic Profile Manager Load should fail a load if the profile doesn't have the required dependencies listed when loaded 1`] = `"Profile validation error during load of profile \\"strawberry_no_apple\\" of type \\"strawberry\\". Error Details: Profile type \\"strawberry\\" specifies a required dependency of type \\"apple\\" on the \\"strawberry\\" profile type configuration document. A dependency of type \\"apple\\" was NOT listed on the input profile."`; - -exports[`Basic Profile Manager Load should fail a load request if the profile is not found 1`] = `"Profile \\"missing_apple\\" of type \\"apple\\" does not exist."`; - -exports[`Basic Profile Manager Load should fail a load request if the profile loaded does not conform to the schema 1`] = ` -"Profile validation error during load of profile \\"misshapen_apple\\" of type \\"apple\\". Error Details: Errors located in profile \\"misshapen_apple\\" of type \\"apple\\": -profile requires property \\"rotten\\" -profile requires property \\"age\\" -" -`; - -exports[`Basic Profile Manager Load should fail a profile load with two dependencies, one of which has it's own dependency that is circular 1`] = ` -"An error occurred while loading the dependencies of profile \\"apple_has_circular\\" of type \\"apple\\". Dependency load list: -Type: \\"strawberry\\" Name: \\"chocolate_covered\\" -Type: \\"banana\\" Name: \\"banana_with_grape_dep\\" - -Error Details: An error occurred while loading the dependencies of profile \\"banana_with_grape_dep\\" of type \\"banana\\". Dependency load list: -Type: \\"grape\\" Name: \\"grape_with_banana_circular_dep\\" - -Error Details: An error occurred while loading the dependencies of profile \\"grape_with_banana_circular_dep\\" of type \\"grape\\". Dependency load list: -Type: \\"banana\\" Name: \\"banana_with_grape_dep\\" - -Error Details: A circular profile dependency was detected. Profile \\"banana_with_grape_dep\\" of type \\"banana\\" either points directly to itself OR a dependency of this profile points to this profile." -`; - -exports[`Basic Profile Manager Load should fail a profile load with two dependencies, one of which has it's own dependency which is not found 1`] = ` -"An error occurred while loading the dependencies of profile \\"apples_and_grapes_not_found_and_strawberries_and_bananas\\" of type \\"apple\\". Dependency load list: -Type: \\"strawberry\\" Name: \\"chocolate_strawberries\\" -Type: \\"banana\\" Name: \\"bananas_error_and_grapes\\" - -Error Details: An error occurred while loading the dependencies of profile \\"bananas_error_and_grapes\\" of type \\"banana\\". Dependency load list: -Type: \\"grape\\" Name: \\"no_grapes\\" - -Error Details: Profile \\"no_grapes\\" of type \\"grape\\" does not exist." -`; - -exports[`Basic Profile Manager Load should fail a profile load with two dependencies, one of which has it's own dependency with an error 1`] = ` -"An error occurred while loading the dependencies of profile \\"apples_and_grapes_with_error_and_strawberries_and_bananas\\" of type \\"apple\\". Dependency load list: -Type: \\"strawberry\\" Name: \\"chocolate_strawberries\\" -Type: \\"banana\\" Name: \\"bananas_and_error_grapes\\" - -Error Details: An error occurred while loading the dependencies of profile \\"bananas_and_error_grapes\\" of type \\"banana\\". Dependency load list: -Type: \\"grape\\" Name: \\"bad_grapes\\" - -Error Details: Profile validation error during load of profile \\"bad_grapes\\" of type \\"grape\\". Error Details: Errors located in profile \\"bad_grapes\\" of type \\"grape\\": -profile requires property \\"description\\" -profile requires property \\"color\\" -" -`; - -exports[`Basic Profile Manager Load should fail if the default doesn't exist 1`] = `"No default profile set for type \\"orange\\"."`; - -exports[`Basic Profile Manager Load should fail the request if no profile name is specified and default profile is set but not found 1`] = ` -"Your default profile named missing_orange does not exist for type orange. -To change your default profile, run \\"undefined profiles set-default orange \\"." -`; - -exports[`Basic Profile Manager Load should handle a read error 1`] = `"Read error!"`; - -exports[`Basic Profile Manager Load should load a profile with one dependency 1`] = ` -Object { - "dependenciesLoaded": true, - "dependencyLoadResponses": Array [ - Object { - "dependenciesLoaded": false, - "dependencyLoadResponses": Array [], - "failNotFound": true, - "message": "Profile \\"good_apple\\" of type \\"apple\\" loaded successfully.", - "name": "good_apple", - "profile": Object { - "age": 1, - "description": "A tasty apple", - "rotten": false, - }, - "type": "apple", - }, - ], - "failNotFound": true, - "message": "Profile \\"sweet_strawberry\\" of type \\"strawberry\\" loaded successfully.", - "name": "sweet_strawberry", - "profile": Object { - "amount": 1000, - "dependencies": Array [ - Object { - "name": "good_apple", - "type": "apple", - }, - ], - "description": "Super sweet strawberries", - }, - "type": "strawberry", -} -`; - -exports[`Basic Profile Manager Load should load a profile with two dependencies 1`] = ` -Object { - "dependenciesLoaded": true, - "dependencyLoadResponses": Array [ - Object { - "dependenciesLoaded": false, - "dependencyLoadResponses": Array [], - "failNotFound": true, - "message": "Profile \\"chocolate_strawberries\\" of type \\"strawberry\\" loaded successfully.", - "name": "chocolate_strawberries", - "profile": Object { - "amount": 1000, - "description": "chocolate covered", - }, - "type": "strawberry", - }, - Object { - "dependenciesLoaded": false, - "dependencyLoadResponses": Array [], - "failNotFound": true, - "message": "Profile \\"bundle_of_bananas\\" of type \\"banana\\" loaded successfully.", - "name": "bundle_of_bananas", - "profile": Object { - "bundle": true, - }, - "type": "banana", - }, - ], - "failNotFound": true, - "message": "Profile \\"apples_and_strawberries_and_bananas\\" of type \\"apple\\" loaded successfully.", - "name": "apples_and_strawberries_and_bananas", - "profile": Object { - "age": 1, - "dependencies": Array [ - Object { - "name": "chocolate_strawberries", - "type": "strawberry", - }, - Object { - "name": "bundle_of_bananas", - "type": "banana", - }, - ], - "description": "A tasty apple", - "rotten": false, - }, - "type": "apple", -} -`; - -exports[`Basic Profile Manager Load should load a profile with two dependencies, one of which has it's own dependency 1`] = ` -Object { - "dependenciesLoaded": true, - "dependencyLoadResponses": Array [ - Object { - "dependenciesLoaded": false, - "dependencyLoadResponses": Array [], - "failNotFound": true, - "message": "Profile \\"chocolate_strawberries\\" of type \\"strawberry\\" loaded successfully.", - "name": "chocolate_strawberries", - "profile": Object { - "amount": 1000, - "description": "chocolate covered", - }, - "type": "strawberry", - }, - Object { - "dependenciesLoaded": true, - "dependencyLoadResponses": Array [ - Object { - "dependenciesLoaded": false, - "dependencyLoadResponses": Array [], - "failNotFound": true, - "message": "Profile \\"green_grapes\\" of type \\"grape\\" loaded successfully.", - "name": "green_grapes", - "profile": Object { - "color": "green", - "description": "Super tasty grapes", - }, - "type": "grape", - }, - ], - "failNotFound": true, - "message": "Profile \\"bananas_and_grapes\\" of type \\"banana\\" loaded successfully.", - "name": "bananas_and_grapes", - "profile": Object { - "bundle": true, - "dependencies": Array [ - Object { - "name": "green_grapes", - "type": "grape", - }, - ], - }, - "type": "banana", - }, - ], - "failNotFound": true, - "message": "Profile \\"apples_and_grapes_and_strawberries_and_bananas\\" of type \\"apple\\" loaded successfully.", - "name": "apples_and_grapes_and_strawberries_and_bananas", - "profile": Object { - "age": 1, - "dependencies": Array [ - Object { - "name": "chocolate_strawberries", - "type": "strawberry", - }, - Object { - "name": "bananas_and_grapes", - "type": "banana", - }, - ], - "description": "A tasty apple", - "rotten": false, - }, - "type": "apple", -} -`; - -exports[`Basic Profile Manager Load should load the default if requested 1`] = `"Profile \\"sweet_blueberry\\" of type \\"blueberry\\" loaded successfully."`; - -exports[`Basic Profile Manager Load should load the default if requested 2`] = ` -Object { - "tart": false, -} -`; - -exports[`Basic Profile Manager Load should not allow us to load a profile with an optional dependency and the optional dependency doesn't exist 1`] = ` -"An error occurred while loading the dependencies of profile \\"strawberry_not_found_apple\\" of type \\"strawberry\\". Dependency load list: -Type: \\"apple\\" Name: \\"missing_apple\\" - -Error Details: Profile \\"missing_apple\\" of type \\"apple\\" does not exist." -`; - -exports[`Basic Profile Manager Load should not fail the request if 'fail not found' is false and the profile was not found 1`] = `"Profile \\"default was requested\\" of type \\"orange\\" was not found, but the request indicated to ignore \\"not found\\" errors. The profile returned is undefined."`; diff --git a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.save.unit.test.ts.snap b/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.save.unit.test.ts.snap deleted file mode 100644 index 950e4aadfa..0000000000 --- a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.save.unit.test.ts.snap +++ /dev/null @@ -1,91 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Basic Profile Manager Save should allow us to save a profile with a dependency 1`] = ` -Object { - "amount": 10000, - "dependencies": Array [ - Object { - "name": "tasty_apples", - "type": "apple", - }, - ], - "description": "Strawberries covered in chocolate.", - "type": "strawberry", -} -`; - -exports[`Basic Profile Manager Save should allow us to save a well-formed profile 1`] = ` -Object { - "age": 1, - "description": "A tasty apple", - "rotten": false, -} -`; - -exports[`Basic Profile Manager Save should detect a blank name when creating a profile 1`] = `"Expect Error: Required parameter 'name' must not be blank"`; - -exports[`Basic Profile Manager Save should detect a missing name when creating a profile 1`] = `"Expect Error: A request was made to save a profile of type \\"apple\\", but no name was supplied."`; - -exports[`Basic Profile Manager Save should detect a type mismatch from the schema for booleans 1`] = ` -"Errors located in profile \\"bad_apple\\" of type \\"apple\\": -rotten is not of a type(s) boolean -" -`; - -exports[`Basic Profile Manager Save should detect a type mismatch from the schema for strings 1`] = ` -"Errors located in profile \\"bad_apple\\" of type \\"apple\\": -description is not of a type(s) string -" -`; - -exports[`Basic Profile Manager Save should detect all missing required fields on the schema 1`] = ` -"Errors located in profile \\"bad_strawberry\\" of type \\"strawberry\\": -profile requires property \\"description\\" -profile requires property \\"amount\\" -" -`; - -exports[`Basic Profile Manager Save should detect if the meta name was specified as the profile name 1`] = `"Expect Error: You cannot specify \\"apple_meta\\" as a profile name. This profile name is reserved for internal Imperative usage."`; - -exports[`Basic Profile Manager Save should detect missing parameters 1`] = `"Expect Error: A request was made to save a profile of type \\"apple\\", but no parameters were supplied."`; - -exports[`Basic Profile Manager Save should detect missing profile 1`] = `"Expect Error: A request was made to save a profile of type \\"apple\\", but no profile was supplied."`; - -exports[`Basic Profile Manager Save should detect that a profile requires a dependency of a certain type 1`] = `"Profile type \\"strawberry\\" specifies a required dependency of type \\"apple\\" on the \\"strawberry\\" profile type configuration document. A dependency of type \\"apple\\" was NOT listed on the input profile."`; - -exports[`Basic Profile Manager Save should detect that the dependencies are not an array 1`] = `"Expect Error: The profile passed (name \\"bad_apple\\" of type \\"apple\\") has dependencies as a property, but it is NOT an array (ill-formed)"`; - -exports[`Basic Profile Manager Save should detect that the dependencies are present, but name is missing 1`] = `"Expect Error: The profile passed (name \\"bad_apple\\" of type \\"apple\\") has dependencies as a property, but an entry does not contain \\"name\\"."`; - -exports[`Basic Profile Manager Save should detect that the dependencies are present, but type is missing 1`] = `"Expect Error: The profile passed (name \\"bad_apple\\" of type \\"apple\\") has dependencies as a property, but an entry does not contain \\"type\\"."`; - -exports[`Basic Profile Manager Save should fail a save request if a profile has more properties than defined on the schema 1`] = ` -"Errors located in profile \\"tasty_apple\\" of type \\"apple\\": -profile is not allowed to have the additional property \\"seedless\\" -" -`; - -exports[`Basic Profile Manager Save should fail a save request if an error is thrown by write file 1`] = `"Write file unexpected failure"`; - -exports[`Basic Profile Manager Save should fail a save request if the file already exists and overwrite is false 1`] = `"Profile \\"old_apple\\" of type \\"apple\\" already exists and overwrite was NOT specified."`; - -exports[`Basic Profile Manager Save should fail a save request if there is an error writing the meta file 1`] = `"Error writing the meta file"`; - -exports[`Basic Profile Manager Save should not allow a save with a circular dependency 1`] = ` -"Could not save the profile, because one or more dependencies is invalid or does not exist. -Load Error Details: An error occurred while loading the dependencies of profile \\"apple_with_two_req_dep_circular\\" of type \\"apple\\". Dependency load list: -Type: \\"strawberry\\" Name: \\"chocolate_covered\\" -Type: \\"banana\\" Name: \\"banana_with_grape_dep\\" - -Error Details: An error occurred while loading the dependencies of profile \\"banana_with_grape_dep\\" of type \\"banana\\". Dependency load list: -Type: \\"grape\\" Name: \\"grape_with_banana_circular_dep\\" - -Error Details: An error occurred while loading the dependencies of profile \\"grape_with_banana_circular_dep\\" of type \\"grape\\". Dependency load list: -Type: \\"banana\\" Name: \\"banana_with_grape_dep\\" - -Error Details: A circular profile dependency was detected. Profile \\"banana_with_grape_dep\\" of type \\"banana\\" either points directly to itself OR a dependency of this profile points to this profile." -`; - -exports[`Basic Profile Manager Save should not allow a save with no contents 1`] = `"The profile passed (name \\"no_apple_core\\" of type \\"apple\\") does not contain any content."`; - -exports[`Basic Profile Manager Save should not allow us to overwrite a profile if overwrite false (or not specified) 1`] = `"Profile \\"good_apple\\" of type \\"apple\\" already exists and overwrite was NOT specified."`; diff --git a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.unit.test.ts.snap b/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.unit.test.ts.snap deleted file mode 100644 index b574616f7a..0000000000 --- a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.unit.test.ts.snap +++ /dev/null @@ -1,214 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Basic Profile Manager should allow a re-initialize of the environment 1`] = ` -Array [ - Object { - "message": "Profile environment re-initialized for type \\"apple\\".", - }, - Object { - "message": "Profile environment re-initialized for type \\"strawberry\\".", - }, - Object { - "message": "Profile environment initialized for type \\"banana\\".", - }, - Object { - "message": "Profile environment re-initialized for type \\"grape\\".", - }, -] -`; - -exports[`Basic Profile Manager should allow us to set the default in the meta profile 1`] = `"Default profile for type \\"blueberry\\" set to \\"tart_blueberry\\"."`; - -exports[`Basic Profile Manager should create an instance and read all configurations from the meta files 1`] = ` -Array [ - Object { - "schema": Object { - "description": "The simple apple configuration", - "properties": Object { - "age": Object { - "type": "number", - }, - "description": Object { - "type": "string", - }, - "rotten": Object { - "type": "boolean", - }, - }, - "required": Array [ - "description", - "rotten", - "age", - ], - "title": "The simple apple configuration", - "type": "object", - }, - "type": "apple", - }, - Object { - "schema": Object { - "description": "The simple strawberry configuration", - "properties": Object { - "amount": Object { - "type": "number", - }, - "description": Object { - "type": "string", - }, - }, - "required": Array [ - "description", - "amount", - ], - "title": "The simple strawberry configuration", - "type": "object", - }, - "type": "strawberry", - }, - Object { - "schema": Object { - "description": "The simple banana configuration", - "properties": Object { - "bundle": Object { - "type": "boolean", - }, - "description": Object { - "type": "string", - }, - }, - "required": Array [ - "bundle", - ], - "title": "The simple banana configuration", - "type": "object", - }, - "type": "banana", - }, - Object { - "schema": Object { - "description": "The simple banana configuration", - "properties": Object { - "color": Object { - "type": "string", - }, - "description": Object { - "type": "string", - }, - }, - "required": Array [ - "description", - "color", - ], - "title": "The simple banana configuration", - "type": "object", - }, - "type": "grape", - }, -] -`; - -exports[`Basic Profile Manager should detect blank profile directory on initialize 1`] = `"Expect Error: A request was made to initialize the profile environment, but the profile root directory was not supplied."`; - -exports[`Basic Profile Manager should detect if the type is blank 1`] = `"Expect Error: No profile type supplied on the profile manager parameters."`; - -exports[`Basic Profile Manager should detect if the type is undefined 1`] = `"Expect Error: No profile type supplied on the profile manager parameters."`; - -exports[`Basic Profile Manager should detect ill formed profiles during a load all 1`] = ` -"An error occurred attempting to load all profiles of every type. Load List: -Loading \\"good_apple\\" of type \\"apple\\" -Loading \\"tasty_apples\\" of type \\"apple\\" -Loading \\"strawberry_and_apple\\" of type \\"strawberry\\" -Error Details: \\"Profile validation error during load of profile \\"good_apple\\" of type \\"apple\\". Error Details: Profile type \\"apple\\" specifies a required dependency of type \\"strawberry\\" on the \\"apple\\" profile type configuration document. A dependency of type \\"strawberry\\" was NOT listed on the input profile.\\"" -`; - -exports[`Basic Profile Manager should detect missing configuration on initialize 1`] = `"Expect Error: A request was made to initialize the profile environment, but no configuration documents were supplied."`; - -exports[`Basic Profile Manager should detect missing parms on initialize 1`] = `"Expect Error: A request was made to initialize the profile environment, but no parameters were supplied."`; - -exports[`Basic Profile Manager should detect missing profile directory on initialize 1`] = `"Expect Error: A request was made to initialize the profile environment, but the profile root directory was not supplied."`; - -exports[`Basic Profile Manager should detect no parms when instantiating 1`] = `"Expect Error: Profile Manager input parms not supplied."`; - -exports[`Basic Profile Manager should detect that the configuration passed is not an array 1`] = `"Expect Error: A request was mad to initialize the profile environment, but the configuration provided is invalid (not an array or of length 0)."`; - -exports[`Basic Profile Manager should detect that the profile directory is blank 1`] = `"Expect Error: No profile root directory supplied on the profile manager parameters"`; - -exports[`Basic Profile Manager should detect that the profile directory is undefined 1`] = `"Expect Error: No profile root directory supplied on the profile manager parameters"`; - -exports[`Basic Profile Manager should fail a create if no configurations and passed and none can be read from disk 1`] = `"An error occurred collecting all configurations from the profile root directory \\"__tests__/__results__/test_profiles/root/dir/\\". Please supply the configurations on the profile manager constructor parameters OR initialize the profile manager environment. Details: No profile configurations found. Please initialize the profile manager OR supply the configurations to the profile manager."`; - -exports[`Basic Profile Manager should fail a request to set the default if the profile is not found 1`] = `"Cannot update default profile for type \\"blueberry\\". The profile name specified (\\"bad_blueberry\\") does not exist. Please create before attempting to set the default."`; - -exports[`Basic Profile Manager should initialize the environment 1`] = ` -Array [ - Object { - "message": "Profile environment initialized for type \\"apple\\".", - }, - Object { - "message": "Profile environment initialized for type \\"strawberry\\".", - }, - Object { - "message": "Profile environment initialized for type \\"banana\\".", - }, - Object { - "message": "Profile environment initialized for type \\"grape\\".", - }, -] -`; - -exports[`Basic Profile Manager should load all profiles 1`] = ` -Array [ - Object { - "dependenciesLoaded": false, - "dependencyLoadResponses": Array [], - "failNotFound": true, - "message": "Profile \\"good_apple\\" of type \\"apple\\" loaded successfully.", - "name": "good_apple", - "profile": Object { - "age": 1, - "description": "A tasty apple", - "rotten": false, - }, - "type": "apple", - }, - Object { - "dependenciesLoaded": false, - "dependencyLoadResponses": Array [], - "failNotFound": true, - "message": "Profile \\"tasty_apples\\" of type \\"apple\\" loaded successfully.", - "name": "tasty_apples", - "profile": Object { - "age": 1, - "description": "tasty", - "rotten": false, - }, - "type": "apple", - }, - Object { - "dependenciesLoaded": false, - "dependencyLoadResponses": Array [], - "failNotFound": true, - "message": "Profile \\"strawberry_and_apple\\" of type \\"strawberry\\" loaded successfully.", - "name": "strawberry_and_apple", - "profile": Object { - "amount": 1000, - "dependencies": Array [ - Object { - "name": "good_apple", - "type": "apple", - }, - ], - "description": "Tasty", - }, - "type": "strawberry", - }, -] -`; - -exports[`Basic Profile Manager should only initialize types not already defined in the environment 1`] = ` -Array [ - Object { - "message": "Profile environment initialized for type \\"banana\\".", - }, -] -`; diff --git a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.update.unit.test.ts.snap b/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.update.unit.test.ts.snap deleted file mode 100644 index a5731ad124..0000000000 --- a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.update.unit.test.ts.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Basic Profile Manager Update should allow us to update a profile 1`] = `"Profile \\"good_apple\\" of type \\"apple\\" updated successfully."`; - -exports[`Basic Profile Manager Update should detect missing name parameter 1`] = `"Expect Error: An update for a profile of type \\"apple\\" was requested, but no name was specified."`; - -exports[`Basic Profile Manager Update should detect missing parameters 1`] = `"Expect Error: An update for a profile of type \\"apple\\" was requested, but no parameters were specified."`; diff --git a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.validate.unit.test.ts.snap b/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.validate.unit.test.ts.snap deleted file mode 100644 index 0b4000e40e..0000000000 --- a/packages/imperative/src/profiles/__tests__/__snapshots__/BasicProfileManager.validate.unit.test.ts.snap +++ /dev/null @@ -1,42 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Basic Profile Manager Validate should be able to detect a type mismatch from the schema for booleans 1`] = ` -"Errors located in profile \\"bad_apple\\" of type \\"apple\\": -rotten is not of a type(s) boolean -" -`; - -exports[`Basic Profile Manager Validate should be able to detect a type mismatch from the schema for strings 1`] = ` -"Errors located in profile \\"bad_apple\\" of type \\"apple\\": -description is not of a type(s) string -" -`; - -exports[`Basic Profile Manager Validate should be able to detect all missing required fields on the schema 1`] = ` -"Errors located in profile \\"bad_strawberry\\" of type \\"strawberry\\": -profile requires property \\"description\\" -profile requires property \\"amount\\" -" -`; - -exports[`Basic Profile Manager Validate should be able to detect that a profile requires a dependency of a certain type 1`] = `"Profile type \\"strawberry\\" specifies a required dependency of type \\"apple\\" on the \\"strawberry\\" profile type configuration document. A dependency of type \\"apple\\" was NOT listed on the input profile."`; - -exports[`Basic Profile Manager Validate should be able to detect that the dependencies are present, but type is missing 1`] = `"Expect Error: The profile passed (name \\"bad_apple\\" of type \\"apple\\") has dependencies as a property, but an entry does not contain \\"type\\"."`; - -exports[`Basic Profile Manager Validate should detect a missing profile name 1`] = `"Expect Error: The profile passed does not contain a name (type: \\"apple\\") OR the name property specified is not of type \\"string\\"."`; - -exports[`Basic Profile Manager Validate should detect a that we are attempting to use the meta name 1`] = `"Expect Error: You cannot specify \\"apple_meta\\" as a profile name. This profile name is reserved for internal Imperative usage."`; - -exports[`Basic Profile Manager Validate should detect that the dependencies are not an array 1`] = `"Expect Error: The profile passed (name \\"bad_apple\\" of type \\"apple\\") has dependencies as a property, but it is NOT an array (ill-formed)"`; - -exports[`Basic Profile Manager Validate should detect that the dependencies are present, but name is missing 1`] = `"Expect Error: The profile passed (name \\"bad_apple\\" of type \\"apple\\") has dependencies as a property, but an entry does not contain \\"name\\"."`; - -exports[`Basic Profile Manager Validate should detect undefined parms 1`] = `"Expect Error: A request was made to validate a profile (of type \\"apple\\"), but no parameters were specified."`; - -exports[`Basic Profile Manager Validate should fail a save request if a profile has more properties than defined on the schema 1`] = ` -"Errors located in profile \\"good_apple\\" of type \\"apple\\": -profile is not allowed to have the additional property \\"seedless\\" -" -`; - -exports[`Basic Profile Manager Validate should validate a well formed profile successfully 1`] = `"Profile \\"good_apple\\" of type \\"apple\\" is valid."`; diff --git a/packages/imperative/src/profiles/index.ts b/packages/imperative/src/profiles/index.ts index 1e761a6387..ec970a46f5 100644 --- a/packages/imperative/src/profiles/index.ts +++ b/packages/imperative/src/profiles/index.ts @@ -18,42 +18,9 @@ export * from "./src/doc/definition/IProfile"; export * from "./src/doc/definition/IProfileDependency"; export * from "./src/doc/definition/IProfileProperty"; export * from "./src/doc/definition/IProfileSchema"; -export * from "./src/doc/api/IProfileManagerFactory"; -export * from "./src/doc/parms/IDeleteProfile"; -export * from "./src/doc/parms/ILoadProfile"; export * from "./src/doc/parms/IProfileManager"; -export * from "./src/doc/parms/IProfileManagerInit"; -export * from "./src/doc/parms/ISaveProfile"; -export * from "./src/doc/parms/ISaveProfileFromCliArgs"; -export * from "./src/doc/parms/ISetDefaultProfile"; -export * from "./src/doc/parms/IUpdateProfile"; -export * from "./src/doc/parms/IUpdateProfileFromCliArgs"; -export * from "./src/doc/parms/IValidateProfile"; -export * from "./src/doc/parms/IValidateProfileForCLI"; -export * from "./src/doc/parms/IValidateProfileWithSchema"; - -export * from "./src/doc/api/IProfileManagerFactory"; - -export * from "./src/doc/response/IProfileDeleted"; -export * from "./src/doc/response/IProfileInitialized"; export * from "./src/doc/response/IProfileLoaded"; -export * from "./src/doc/response/IProfileSaved"; -export * from "./src/doc/response/IProfileUpdated"; -export * from "./src/doc/response/IProfileValidated"; -export * from "./src/utils/ProfileIO"; +export * from "./src/utils/V1ProfileRead"; export * from "./src/utils/ProfileUtils"; -export * from "./src/utils"; - -export * from "./src/validation/api/ProfileValidator"; - -export * from "./src/validation/doc/IProfileValidationPlan"; -export * from "./src/validation/doc/IProfileValidationReport"; -export * from "./src/validation/doc/IProfileValidationTask"; -export * from "./src/validation/doc/IProfileValidationTaskResult"; - -export * from "./src/BasicProfileManager"; -export * from "./src/BasicProfileManagerFactory"; - -export * from "./src/abstract/AbstractProfileManagerFactory"; diff --git a/packages/imperative/src/profiles/src/BasicProfileManager.ts b/packages/imperative/src/profiles/src/BasicProfileManager.ts deleted file mode 100644 index 1a705a1094..0000000000 --- a/packages/imperative/src/profiles/src/BasicProfileManager.ts +++ /dev/null @@ -1,353 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { AbstractProfileManager } from "./abstract/AbstractProfileManager"; -import { - IDeleteProfile, - ILoadProfile, - IMetaProfile, - IProfile, - IProfileDeleted, - IProfileInitialized, - IProfileLoaded, - IProfileManagerInit, - IProfileSaved, - IProfileTypeConfiguration, - IProfileUpdated, - IProfileValidated, - ISaveProfile, - IUpdateProfile, - IValidateProfileWithSchema -} from "./doc"; - -import { ImperativeExpect } from "../../expect"; -import { ImperativeError } from "../../error"; -import { ProfileIO } from "./utils"; - -/** - * Basic Profile Manager is the most basic implementation of the Imperative Profile Manager. In general, it invokes - * all of the utility/services from the Abstract Profile manager to load, save, delete, validate, etc. Imperative - * profiles. See the "AbstractProfileManager" header for more profile management details. - * - * The main differences between the abstract and the basic include: - * - * 1) The "loadAll()" API in the basic profile manager loads ALL profiles from all types. - * 2) The Basic Profile Manager includes the "initialize()" API, which will create all type directories and persist - * the schema in the meta files. - * - * The Basic Profile Manager can be used "stand-alone" from an Imperative CLI. The intent is to provide apps built - * using Imperative CLI's to take advantage of the profiles that the user has defined, without having to "locate" the - * configuration documents used to construct the CLI's. This is why the initialize() API persists the configuration - * documents within the meta files for each type. - * - * @export - * @class BasicProfileManager - * @extends {AbstractProfileManager} - * @template T - */ -export class BasicProfileManager extends AbstractProfileManager { - /** - * Static method to initialize the profile environment. Accepts the profile root directory (normally supplied by - * your Imperative configuration documents) and all profile "type" configuration documents and constructs the directories - * needed to manage profiles of all types. You must execute this method before beginning to use profiles OR you must - * supply all the type configuration documents (normally obtained from your Imperative configuration document) to - * the constructor of - * @static - * @param {IProfileManagerInit} parms - * @returns {Promise} - * @memberof AbstractProfileManager - */ - public static async initialize(parms: IProfileManagerInit): Promise { - // Validate the input parameters - TODO: Validate all - ImperativeExpect.toNotBeNullOrUndefined( - parms, - `A request was made to initialize the profile environment, but no parameters were supplied.` - ); - ImperativeExpect.keysToBeDefined(parms, ["configuration"], - `A request was made to initialize the profile environment, but no configuration documents were supplied.` - ); - ImperativeExpect.keysToBeDefinedAndNonBlank(parms, ["profileRootDirectory"], - `A request was made to initialize the profile environment, but the profile root directory was not supplied.` - ); - ImperativeExpect.keysToBeAnArray(parms, true, ["configuration"], - `A request was mad to initialize the profile environment, but the configuration provided is invalid (not an array or of length 0).` - ); - - // Set any defaults - parms.reinitialize = (parms.reinitialize == null) ? false : parms.reinitialize; - - // Create the profile root directory (if necessary) - ProfileIO.createProfileDirs(parms.profileRootDirectory); - - // Iterate through the types and create this types configuration document - create a new instance of the - // Manager to create the other types - const responses: IProfileInitialized[] = []; - for (const config of parms.configuration) { - - // Construct the profile type directory - const profileTypeRootDir = parms.profileRootDirectory + "/" + config.type + "/"; - ProfileIO.createProfileDirs(profileTypeRootDir); - - // Meta file path and name - const metaFilePath = profileTypeRootDir + config.type - + AbstractProfileManager.META_FILE_SUFFIX + AbstractProfileManager.PROFILE_EXTENSION; - - // Construct the default meta file - const defaultMetaFile: IMetaProfile = { - defaultProfile: undefined, - configuration: config - }; - - // If the directory doesn't exist, create it and the default meta file for this type - // If the directory exists and re-init was specified, write out the default meta file - // If it exists and re-init was not specified, leave it alone - if (!ProfileIO.exists(metaFilePath)) { - ProfileIO.writeMetaFile(defaultMetaFile, metaFilePath); - responses.push({ - message: `Profile environment initialized for type "${config.type}".` - }); - } else if (parms.reinitialize) { - ProfileIO.writeMetaFile(defaultMetaFile, metaFilePath); - responses.push({ - message: `Profile environment re-initialized for type "${config.type}".` - }); - } - } - - return responses; - } - - /** - * Loads all profiles from every type. Profile types are deteremined by reading all directories within the - * profile root directory. - * @returns {Promise} - The list of all profiles for every type - * @memberof BasicProfileManager - */ - public async loadAll(): Promise { - this.log.trace(`Loading all profiles...`); - // Load all the other profiles for other types - const loadTheirProfiles: any[] = []; - let loadList: string = ""; - for (const typeConfig of this.profileTypeConfigurations) { - const typeProfileManager = new BasicProfileManager({ - profileRootDirectory: this.profileRootDirectory, - typeConfigurations: this.profileTypeConfigurations, - type: typeConfig.type, - logger: this.log, - loadCounter: this.loadCounter - }); - - // Get all the profile names for the type and attempt to load every one - const names: string[] = typeProfileManager.getAllProfileNames(); - for (const name of names) { - this.log.debug(`Loading profile "${name}" of type "${typeConfig.type}".`); - loadTheirProfiles.push(typeProfileManager.load({name, failNotFound: true, loadDependencies: false})); - loadList += `\nLoading "${name}" of type "${typeConfig.type}"`; - } - } - - // Construct the full list for return - let allProfiles: IProfileLoaded[] = []; - try { - this.log.trace(`Awaiting all loads...`); - const theirProfiles = await Promise.all(loadTheirProfiles); - for (const theirs of theirProfiles) { - allProfiles = allProfiles.concat(theirs); - } - this.log.trace(`All loads complete.`); - } catch (e) { - const msg: string = `An error occurred attempting to load all profiles of every type. ` + - `Load List: ${loadList}\nError Details: "${e.message}"`; - this.log.error(msg); - throw new ImperativeError({msg}); - } - - return allProfiles; - } - - /** - * Loads all dependencies for the profile specified - returns the list in the response structure. Sub-dependencies - * are also loaded. - * @protected - * @param {string} name - the name of hte profile to load dependencies for - * @param {IProfile} profile - The profile to load dependencies. - * @param {boolean} [failNotFound=true] - Indicates that you want to avoid failing the request for "not found" errors. - * @returns {Promise} - The list of profiles loaded with all dependencies. - * @memberof BasicProfileManager - */ - protected loadDependencies(name: string, profile: IProfile, failNotFound = true): Promise { - return new Promise((dependenciesLoaded, loadFailed) => { - - // Construct a list of promises to load all profiles - const promises: Array> = []; - const responses: IProfileLoaded[] = []; - if (!(profile.dependencies == null)) { - this.log.debug(`Loading dependencies for profile of "${this.profileType}".`); - let list: string = ""; - for (const dependency of profile.dependencies) { - this.log.debug(`Loading dependency "${dependency.name}" of type "${dependency.type}".`); - promises.push(new BasicProfileManager({ - profileRootDirectory: this.profileRootDirectory, - typeConfigurations: this.profileTypeConfigurations, - type: dependency.type, - logger: this.log, - loadCounter: this.loadCounter - }).load({name: dependency.name, failNotFound})); - list += `\nType: "${dependency.type}" Name: "${dependency.name}"`; - } - - // Wait for all the promises to complete - Promise.all(promises).then((loadResponses) => { - this.log.debug(`All dependencies loaded for profile of type "${this.profileType}".`); - // Append the responses for return to caller - for (const response of loadResponses) { - responses.push(response); - } - dependenciesLoaded(responses); - }).catch((loadsFailed) => { - this.log.error(`Failure to load dependencies for profile of type "${this.profileType}". ` + - `Details: ${loadsFailed.message}`); - const err: string = `An error occurred while loading the dependencies of profile ` + - `"${name}" of type "${this.profileType}". Dependency load list: ${list}\n\nError Details: ${loadsFailed.message}`; - loadFailed(new ImperativeError({msg: err, additionalDetails: loadsFailed})); - }); - } else { - this.log.trace(`Profile of type "${this.profileType}" has no dependencies.`); - dependenciesLoaded([]); - } - }); - } - - /** - * Save the profile to disk. First ensures that all dependencies are valid and writes the profile. - * @protected - * @param {ISaveProfile} parms - Save control params - see the interface for full details - * @returns {Promise} - Promise that is fulfilled when complete (or rejected with an Imperative Error) - * @memberof BasicProfileManager - */ - protected async saveProfile(parms: ISaveProfile): Promise { - // Validate that the dependencies listed exist before saving - try { - this.log.debug(`Loading dependencies for profile "${parms.name}" of type "${this.profileType}", ` + - `checking if if they are valid (before save.)`); - await this.loadDependencies(parms.name, parms.profile); - } catch (e) { - throw new ImperativeError({ - msg: `Could not save the profile, because one or more dependencies is invalid or does not exist.\n` + - `Load Error Details: ${e.message}` - }); - } - - // Construct the full file path, write to disk, and return the response - this.log.info(`Saving profile "${parms.name}" of type "${this.profileType}"...`); - const path = this.constructFullProfilePath(parms.name); - ProfileIO.writeProfile(path, parms.profile); - this.log.info(`Profile "${parms.name}" of type "${this.profileType}" saved.`); - return { - path, - overwritten: parms.overwrite || false, - message: `Profile ("${parms.name}" of type "${this.profileType}") ` + - `successfully written: ${path}`, - profile: parms.profile - }; - } - - /** - * Load a profile from disk - invokes the "loadSpecificProfile" method in the abstract to perform the load. - * @protected - * @param {ILoadProfile} parms - Load control params - see the interface for full details - * @returns {Promise} - Promise that is fulfilled when complete (or rejected with an Imperative Error) - * @memberof BasicProfileManager - */ - protected async loadProfile(parms: ILoadProfile): Promise { - const loadName: string = (parms.loadDefault || false) ? this.getDefaultProfileName() : parms.name; - this.log.debug(`Loading profile "${loadName}" (load default: "${parms.loadDefault}") of type "${this.profileType}".`); - return this.loadSpecificProfile(loadName, parms.failNotFound, parms.loadDependencies); - } - - /** - * Delete a profile from disk - invokes the "deleteProfileFromDisk" method in the abstract to perform the load. - * @protected - * @param {IDeleteProfile} parms - Delete control params - see the interface for full details - * @returns {Promise} - Promise that is fulfilled when complete (or rejected with an Imperative Error) - * @memberof BasicProfileManager - */ - protected async deleteProfile(parms: IDeleteProfile): Promise { - this.log.trace(`Removing profile "${parms.name}" of type "${this.profileType}".`); - const path = this.deleteProfileFromDisk(parms.name); - this.log.debug(`Profile "${parms.name}" of type "${this.profileType}" successfully deleted.`); - return { - path, - message: `Profile "${parms.name}" of type "${this.profileType}" deleted successfully.` - }; - } - - /** - * Validate profile - ensures that the profile is valid agaisnt the schema and configuration document - * @protected - * @param {IValidateProfileWithSchema} parms - Validate control params - see the interface for full details - * @returns {Promise} - Promise that is fulfilled when complete (or rejected with an Imperative Error) - * @memberof BasicProfileManager - */ - protected async validateProfile(parms: IValidateProfileWithSchema): Promise { - this.log.trace(`Validating profile "${parms.name}" of type "${this.profileType}"`); - // Ensure that the profile is not empty - if (this.isProfileEmpty(parms.profile)) { - throw new ImperativeError({ - msg: `The profile passed (name "${parms.name}" of type ` + - `"${this.profileType}") does not contain any content.` - }); - } - - // If the configuration indicates this profile type has required dependencies, ensure that those are specified - // on the profile object passed. - this.validateRequiredDependenciesAreSpecified(parms.profile); - - // Validate the profile agaisnt the schema - this.validateProfileAgainstSchema(parms.name, parms.profile, parms.strict); - - // Return the response - this.log.debug(`Profile "${parms.name}" of type "${this.profileType}" is valid.`); - return { - message: `Profile "${parms.name}" of type "${this.profileType}" is valid.` - }; - } - - /** - * Update a profile - Accepts the "new" version of the profile and overwrites the existing profile on disk. - * @protected - * @param {IUpdateProfile} parms - Update control params - see the interface for full details - * @returns {Promise} - Promise that is fulfilled when complete (or rejected with an Imperative Error) - * @memberof BasicProfileManager - */ - protected async updateProfile(parms: IUpdateProfile): Promise { - this.log.trace(`Saving (as part of updating) profile "${parms.name}" of type "${this.profileType}".`); - if (parms.merge) { - this.log.debug(`Profile merging was requested. Loading the old version of the profile ` + - `"${parms.name}" of type "${this.profileType}".`); - const oldProfileLoad = await this.load({name: parms.name, failNotFound: true}); - parms.profile = this.mergeProfiles(oldProfileLoad.profile, parms.profile); - this.log.debug(`Merged profile "${parms.name}" of type "${this.profileType}" with old version`); - } - const response = await this.save({ - name: parms.name, - type: this.profileType, - profile: parms.profile, - overwrite: true - }); - this.log.trace(`Save of profile "${parms.name}" of type "${this.profileType}" complete.`); - return { - path: response.path, - message: `Profile "${parms.name}" of type "${this.profileType}" updated successfully.`, - profile: response.profile - }; - } -} diff --git a/packages/imperative/src/profiles/src/BasicProfileManagerFactory.ts b/packages/imperative/src/profiles/src/BasicProfileManagerFactory.ts deleted file mode 100644 index c8695635ed..0000000000 --- a/packages/imperative/src/profiles/src/BasicProfileManagerFactory.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { AbstractProfileManagerFactory } from "./abstract/AbstractProfileManagerFactory"; -import { IProfileTypeConfiguration } from "./doc/config/IProfileTypeConfiguration"; -import { BasicProfileManager } from "./BasicProfileManager"; - -/** - * A basic profile mananger factory - returns instances of profile managers depending on the types passed. - * @export - * @class BasicProfileManagerFactory - * @extends {AbstractProfileManagerFactory} - */ -export class BasicProfileManagerFactory extends AbstractProfileManagerFactory { - /** - * The root directory where the profiles will be found. - * @private - * @type {string} - * @memberof BasicProfileManagerFactory - */ - private mProfilesRootDirectory: string; - - /** - * Type configurations for the basic profile manager - * @private - * @type {IProfileTypeConfiguration[]} - * @memberof BasicProfileManagerFactory - */ - private mTypeConfigurations: IProfileTypeConfiguration[]; - - /** - * Creates an instance of BasicProfileManagerFactory. - * @param {string} profilesRootDirectory - The root directory to find your profiles - * @memberof BasicProfileManagerFactory - */ - constructor(profilesRootDirectory: string, typeConfigurations?: IProfileTypeConfiguration[]) { - super(); - this.mProfilesRootDirectory = profilesRootDirectory; - this.mTypeConfigurations = typeConfigurations; - } - - /** - * Returns a new instance of the basic profile manager for the type. - * @param {string} type - the profile type to manager. - * @returns {BasicProfileManager} - The profile manager instance for the type. - * @memberof BasicProfileManagerFactory - */ - public getManager(type: string): BasicProfileManager { - return new BasicProfileManager({ - type, - profileRootDirectory: this.profilesRootDirectory, - typeConfigurations: this.typeConfigurations - }); - } - - /** - * Accessor for the profiles root directory - * @readonly - * @private - * @type {string} - * @memberof BasicProfileManagerFactory - */ - private get profilesRootDirectory(): string { - return this.mProfilesRootDirectory; - } - - /** - * Accessor for the type configurations - * @readonly - * @private - * @type {IProfileTypeConfiguration[]} - * @memberof BasicProfileManagerFactory - */ - private get typeConfigurations(): IProfileTypeConfiguration[] { - return this.mTypeConfigurations; - } -} diff --git a/packages/imperative/src/profiles/src/abstract/AbstractProfileManager.ts b/packages/imperative/src/profiles/src/abstract/AbstractProfileManager.ts deleted file mode 100644 index b1240cfd3c..0000000000 --- a/packages/imperative/src/profiles/src/abstract/AbstractProfileManager.ts +++ /dev/null @@ -1,1373 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ImperativeExpect } from "../../../expect"; -import { inspect } from "util"; -import { Logger } from "../../../logger"; -import { ImperativeError } from "../../../error"; -import * as nodePath from "path"; -import { - IDeleteProfile, - ILoadProfile, - IMetaProfile, - IProfile, - IProfileDeleted, - IProfileDependency, - IProfileLoaded, - IProfileManager, - IProfileSaved, - IProfileSchema, - IProfileTypeConfiguration, - IProfileUpdated, - IProfileValidated, - ISaveProfile, - IUpdateProfile, - IValidateProfile, - IValidateProfileWithSchema, - ILoadAllProfiles -} from "../doc/"; -import { ProfileIO, ProfileUtils } from "../utils"; -import { ImperativeConfig } from "../../../utilities"; - -const SchemaValidator = require("jsonschema").Validator; - -/** - * The abstract profile manager contains most (if not all in some cases) methods to manage Imperative profiles. Profiles - * are user configuration documents intended to be used on commands, as a convenience, to supply a slew of additional - * input and configuration (normally more than would be feasible as command arguments). See the "IProfile" interface - * for a detailed description of profiles, their use case, and examples. - * - * The abstract manager is implemented by (at least as part of Imperative) the BasicProfileManager. The BasicProfileManager - * implements the save, load, update, etc. methods in, as the name implies, a "basic" way. In general, the abstract - * manager contains all parameter and profile validation code, methods to write/read/etc and the Basic Manager uses - * most of the internal methods to perform the "work". The basic manager does in some cases change the default abstract - * behavior (such as for loadAll profile and loadDependencies). - * - * Imperative, however, uses the the "Cli Profile Manager", which extends the "Basic Profile Manager". The CLI Manager includes - * additional capabilities, such as creating or updating a profile from command line arguments. - * - * In general, Imperative CLI's will use the "Cli Profile Manager", where the "Basic Profile Manager" is normally sufficient - * for usage outside of Imperative (for usage in building extensions to editors, Electron apps, programmatic usage of - * APIs built by implementations of Imperative, etc.), although either can be used. - * - * It is not an absolute requirement, but in the case of an Imperative CLI, the "Basic Profile Manager initialize()" API - * is invoked to create the required directories and sub-directories. This is NOT a requirement, but avoiding "initialize()" - * means you must supply all configuration information to the manager when creating an instance. See the "initialize()" API - * method in the "BasicProfileManager" for full details. - * - * @export - * @abstract - * @class AbstractProfileManager - */ -export abstract class AbstractProfileManager { - /** - * The default profile file extension (YAML format) - all profiles are stored in YAML format including - * the meta profile file. - * @static - * @type {string} - * @memberof ProfileManager - */ - public static readonly PROFILE_EXTENSION: string = ".yaml"; - - /** - * The meta file suffix - always appended to the meta file to distinguish from other profiles. Users then cannot - * supply a profile name that would conflict with the meta file. - * @static - * @type {string} - * @memberof AbstractProfileManager - */ - public static readonly META_FILE_SUFFIX: string = "_meta"; - - /** - * Load counter for this instance of the imperative profile manager. The load counter ensures that we are not - * attempting to load circular dependencies by checking if a load (with dependencies) is attempting a load of - * the same profile twice. The counts are reset when the loads complete, so state should be preserved correctly. - * @private - * @static - * @type {Map} - * @memberof AbstractProfileManager - */ - private mLoadCounter: Map = new Map(); - - /** - * Parameters passed on the constructor (normally used to create additional instances of profile manager objects) - * @private - * @type {IProfileManager} - * @memberof AbstractProfileManager - */ - private mConstructorParms: IProfileManager; - - /** - * The profile root directory is normally supplied on an Imperative configuration document, but it is the - * location where all profile type directories are stored. - * @private - * @type {string} - * @memberof AbstractProfileManager - */ - private mProfileRootDirectory: string; - - /** - * The full set of profile type configurations. The manager needs to ensure that A) the profile type configuration - * is among the set (because it contains schema and dependency specifications) and B) That other type configurations - * are available to verify/load dependencies, etc. - * @private - * @type {T[]} - * @memberof AbstractProfileManager - */ - private mProfileTypeConfigurations: T[]; - - /** - * The profile "type" for this manager - indicating the profile/schema that this manager is working directly with. - * @private - * @type {string} - * @memberof AbstractProfileManager - */ - private mProfileType: string; - - /** - * The profile configuration document for the "type" defined to this manager. Contains the schema and dependency - * specifications for the profile type. - * @private - * @type {T} - * @memberof AbstractProfileManager - */ - private mProfileTypeConfiguration: T; - - /** - * The profile schema for the "type". The JSON schema is used to validate any profiles loaded or saved by this - * profile manager for the type. - * @private - * @type {IProfileSchema} - * @memberof AbstractProfileManager - */ - private mProfileTypeSchema: IProfileSchema; - - /** - * The root directory for the type (contained within the profile root directory). - * @private - * @type {string} - * @memberof AbstractProfileManager - */ - private mProfileTypeRootDirectory: string; - - /** - * The meta file name for this profile type. Of the form "_meta". - * @private - * @type {string} - * @memberof AbstractProfileManager - */ - private mProfileTypeMetaFileName: string; - - /** - * Product display name of the CLI. - * @private - * @type {string} - * @memberof AbstractProfileManager - */ - private mProductDisplayName: string; - - /** - * Logger instance - must be log4js compatible. Can be the Imperative logger (normally), but is required for - * profile manager operation. - * @private - * @type {Logger} - * @memberof AbstractProfileManager - */ - private mLogger: Logger = Logger.getImperativeLogger(); - - /** - * Creates an instance of ProfileManager - Performs basic parameter validation and will create the required - * profile root directory (if it does not exist) and will attempt to load type configurations from the - * existing profile root directory (unless the type definitions are passed on the constructor parameters). - * - * @param {IProfileManager} parms - See the interface for details. - * @memberof ProfileManager - */ - constructor(parms: IProfileManager) { - ImperativeExpect.toNotBeNullOrUndefined(parms, "Profile Manager input parms not supplied."); - ImperativeExpect.keysToBeDefinedAndNonBlank(parms, ["type"], - "No profile type supplied on the profile manager parameters."); - ImperativeExpect.keysToBeDefinedAndNonBlank(parms, ["profileRootDirectory"], - "No profile root directory supplied on the profile manager parameters"); - if (parms.loadCounter != null) { - this.mLoadCounter = parms.loadCounter; - } - this.mLogger = parms.logger == null ? this.mLogger : parms.logger; - this.mProfileType = parms.type; - this.mProfileRootDirectory = parms.profileRootDirectory; - this.mProfileTypeConfigurations = parms.typeConfigurations; - this.mProductDisplayName = parms.productDisplayName; - if (this.profileTypeConfigurations == null || this.profileTypeConfigurations.length === 0) { - try { - this.mProfileTypeConfigurations = this.collectAllConfigurations(); - if (this.mProfileTypeConfigurations.length === 0) { - throw new ImperativeError({ - msg: `No profile configurations found. ` + - `Please initialize the profile manager OR supply the configurations to the profile manager.` - }); - } - } catch (e) { - throw new ImperativeError({ - msg: `An error occurred collecting all configurations ` + - `from the profile root directory "${this.profileRootDirectory}". ` + - `Please supply the configurations on the profile manager constructor parameters ` + - `OR initialize the profile manager environment. Details: ${e.message}`, - additionalDetails: e - }); - } - } - this.mConstructorParms = parms; - this.mProfileTypeConfiguration = ImperativeExpect.arrayToContain(this.mProfileTypeConfigurations, (entry) => { - return entry.type === this.mProfileType; - }, `Could not locate the profile type configuration for "${this.profileType}" within the input configuration list passed.` + - `\n${inspect(this.profileTypeConfigurations, {depth: null})}`); - for (const config of this.profileTypeConfigurations) { - this.validateConfigurationDocument(config); - } - this.mProfileTypeSchema = this.mProfileTypeConfiguration.schema; - this.mProfileTypeRootDirectory = this.createProfileTypeDirectory(); - this.mProfileTypeMetaFileName = this.constructMetaName(); - } - - /** - * Accessor for the load counter (protects against circular loading) - * @readonly - * @protected - * @type {Map} - * @memberof AbstractProfileManager - */ - protected get loadCounter(): Map { - return this.mLoadCounter; - } - - /** - * Accessor for the logger instance - passed on the constructor - * @readonly - * @protected - * @type {Logger} - * @memberof AbstractProfileManager - */ - protected get log(): Logger { - return this.mLogger; - } - - /** - * Accessor the input parameters to the constructor - used sometimes to create other instances of profile managers. - * @readonly - * @protected - * @type {IProfileManager} - * @memberof AbstractProfileManager - */ - protected get managerParameters(): IProfileManager { - return this.mConstructorParms; - } - - /** - * Accessor for the profile type specified on the constructor. - * @readonly - * @protected - * @type {string} - * @memberof AbstractProfileManager - */ - protected get profileType(): string { - return this.mProfileType; - } - - /** - * Accesor for the product display name. - * @readonly - * @protected - * @type {string} - * @memberof AbstractProfileManager - */ - protected get productDisplayName(): string { - return this.mProductDisplayName; - } - - /** - * Accessor for the profile type configuration for this manager. - * @readonly - * @protected - * @type {T} - * @memberof AbstractProfileManager - */ - protected get profileTypeConfiguration(): T { - return this.mProfileTypeConfiguration; - } - - /** - * Accessor for the full set of type configurations - passed on the constructor or obtained from reading - * the profile root directories and meta files. - * @readonly - * @protected - * @type {T[]} - * @memberof AbstractProfileManager - */ - protected get profileTypeConfigurations(): T[] { - return this.mProfileTypeConfigurations; - } - - /** - * Accessor for the schema of this type - JSON schema standard - * @readonly - * @protected - * @type {IProfileSchema} - * @memberof AbstractProfileManager - */ - protected get profileTypeSchema(): IProfileSchema { - return this.mProfileTypeSchema; - } - - /** - * Accessor for the profile type root directory (contained within the profile root directory and named by the type itself) - * @readonly - * @protected - * @type {string} - * @memberof AbstractProfileManager - */ - protected get profileTypeRootDirectory(): string { - return this.mProfileTypeRootDirectory; - } - - /** - * Accessor for the profile meta file name - constructed as "_meta" - * @readonly - * @protected - * @type {string} - * @memberof AbstractProfileManager - */ - protected get profileTypeMetaFileName(): string { - return this.mProfileTypeMetaFileName; - } - - /** - * Accessor for the profile root directory - supplied on the constructor - used to construct the profile type - * directory. - * @readonly - * @protected - * @type {string} - * @memberof AbstractProfileManager - */ - protected get profileRootDirectory(): string { - return this.mProfileRootDirectory; - } - - /** - * Obtains all profile names for the profile "type" specified on the manager. The names are obtained from the - * filesystem (in the profile type directory) and the meta file is NOT returned in the list. - * @returns {string[]} - The list of profile names (obtained from disk). - * @memberof AbstractProfileManager - */ - public getAllProfileNames(): string[] { - return ProfileIO.getAllProfileNames(this.profileTypeRootDirectory, - AbstractProfileManager.PROFILE_EXTENSION, this.constructMetaName()); - } - - /** - * Accessor that returns a copy of of the profile configuration document. - * @readonly - * @type {IProfileTypeConfiguration[]} - * @memberof AbstractProfileManager - */ - public get configurations(): IProfileTypeConfiguration[] { - return JSON.parse(JSON.stringify(this.profileTypeConfigurations == null ? [] : this.profileTypeConfigurations)); - } - - /** - * Save a profile to disk. Ensures that the profile specified is valid (basic and schema validation) and invokes the implementations - * "saveProfile" method to perform the save and formulate the response. - * @template S - * @param {ISaveProfile} parms - See interface for details - * @returns {Promise} - The promise that is fulfilled with the response object (see interface for details) or rejected - * with an Imperative Error. - * @memberof AbstractProfileManager - */ - public async save(parms: S): Promise { - // Validate the input parameters - ImperativeExpect.toNotBeNullOrUndefined(parms, - `A request was made to save a profile of type "${this.profileType}", but no parameters were supplied.`); - ImperativeExpect.keysToBeDefined(parms, ["profile"], - `A request was made to save a profile of type "${this.profileType}", but no profile was supplied.`); - ImperativeExpect.keysToBeDefined(parms, ["name"], - `A request was made to save a profile of type "${this.profileType}", but no name was supplied.`); - - // Ensure that the type is filled in - a mismatch will be thrown if the type indicates a type other than the manager's current type - parms.type = parms.type || this.profileType; - - // Log the invocation - this.log.info(`Saving profile "${parms.name}" of type "${this.profileType}"...`); - - // Perform basic profile object validation (not specific to create - just that the object is correct for our usage here) - this.log.debug(`Validating the profile ("${parms.name}" of type "${this.profileType}") before save.`); - await this.validate({ - name: parms.name, - profile: parms.profile - }); - - // Protect against overwriting the profile - unless explicitly requested - this.protectAgainstOverwrite(parms.name, parms.overwrite || false); - - // Invoke the implementation - this.log.trace(`Invoking save profile of implementation...`); - const response = await this.saveProfile(parms); - if (response == null) { - throw new ImperativeError({msg: `The profile manager implementation did NOT return a profile save response.`}, - {tag: `Internal Profile Management Error`}); - } - - // If the meta file exists - read to ensure that the name of the default is not null or undefined - this can - // happen after the profile environment is initialized for the first time. - if (this.locateExistingProfile(this.constructMetaName())) { - const meta = this.readMeta(this.constructFullProfilePath(this.constructMetaName())); - if (meta.defaultProfile == null) { - this.log.debug(`Setting "${parms.name}" of type "${parms.type}" as the default profile.`); - this.setDefault(parms.name); - } - } else if (parms.updateDefault || this.locateExistingProfile(this.constructMetaName()) == null) { - this.log.debug(`Setting "${parms.name}" of type "${parms.type}" as the default profile.`); - this.setDefault(parms.name); - } - - // Return the save/create response to the caller - this.log.info(`Save API complete for profile "${parms.name}" of type "${this.profileType}".`); - return response; - } - - /** - * Load a profile from disk. Ensures that the parameters are valid and loads the profile specified by name OR the default profile if - * requested. If load default is requested, any name supplied is ignored. - * @template L - * @param {ILoadProfile} parms - See the interface for details. - * @returns {Promise} - The promise that is fulfilled with the response object (see interface for details) or rejected - * with an Imperative Error. - * @memberof AbstractProfileManager - */ - public async load(parms: L): Promise { - // Ensure the correct parameters were supplied - ImperativeExpect.toNotBeNullOrUndefined(parms, `Profile load requested for type "${this.profileType}", but no parameters supplied.`); - - // Set defaults if not present - parms.loadDefault = (parms.loadDefault == null) ? false : parms.loadDefault; - parms.failNotFound = (parms.failNotFound == null) ? true : parms.failNotFound; - parms.loadDependencies = (parms.loadDependencies == null) ? true : parms.loadDependencies; - - // Log the API call - this.log.info(`Loading profile "${parms.name || "default"}" of type "${this.profileType}"...`); - - // If load default is true, avoid the name check - if loading the default, we ignore the name - if (!parms.loadDefault) { - ImperativeExpect.keysToBeDefined(parms, ["name"], `A profile load was requested for type "${this.profileType}", ` + - `but no profile name was specified.`); - } else { - parms.name = this.getDefaultProfileName(); - this.log.debug(`The default profile for type "${this.profileType}" is "${parms.name}".`); - - // If we don't find the default name and we know fail not found is false, then return here - if (parms.name == null) { - if (!parms.failNotFound) { - return this.failNotFoundDefaultResponse("default was requested"); - } else { - this.log.error(`No default profile exists for type "${this.profileType}".`); - throw new ImperativeError({msg: `No default profile set for type "${this.profileType}".`}); - } - } else if (!this.locateExistingProfile(parms.name)) { - this.log.error(`Default profile "${parms.name}" does not exist for type "${this.profileType}".`); - throw new ImperativeError({ - msg: `Your default profile named ${parms.name} does not exist for type ${this.profileType}.\n` + - `To change your default profile, run "${ImperativeConfig.instance.rootCommandName} profiles set-default ` + - `${this.profileType} ".` - }); - } - } - - // Attempt to protect against circular dependencies - if the load count increases to 2 for the same type/name - // Then some profile in the chain attempted to re-load this profile. - const mapKey: string = ProfileUtils.getProfileMapKey(this.profileType, parms.name); - let count = this.loadCounter.get(mapKey); - if (count == null) { - count = 1; - } else { - count++; - } - this.loadCounter.set(mapKey, count); - this.log.debug(`Load count for "type_name" key "${mapKey}" is ${count}`); - if (count >= 2) { - this.log.error(`Circular dependencies detected in profile "${parms.name}" of type "${this.profileType}".`); - throw new ImperativeError({ - msg: `A circular profile dependency was detected. Profile "${parms.name}" of type "${this.profileType}" ` + - `either points directly to itself OR a dependency of this profile points to this profile.` - }); - } - - // Invoke the implementation - let response; - try { - this.log.debug(`Invoking the implementation to load profile "${parms.name}" of type "${this.profileType}".`); - response = await this.loadProfile(parms); - } catch (e) { - this.log.error(`Load implementation error: ${e.message}`); - this.loadCounter.set(mapKey, 0); - throw e; - } - - // Reset the load counter - this.loadCounter.set(mapKey, 0); - - this.log.info(`Load API completed for profile "${parms.name}" of type "${this.profileType}".`); - return response; - } - - /** - * Validate a profile. Includes basic and schema validation. Can be called explicitly, but is also called during - * loads and saves to protect the integrity of the profiles against the type definitions. - * @template V - * @param {IValidateProfile} parms - See the interface for details - * @returns {Promise} - The promise that is fulfilled with the response object (see interface for details) or rejected - * with an Imperative Error. - * @memberof AbstractProfileManager - */ - public async validate(parms: V): Promise { - // Ensure that parms are passed - ImperativeExpect.toNotBeNullOrUndefined(parms, `A request was made to validate a profile ` + - `(of type "${this.profileType}"), but no parameters were specified.`); - - // Ensure defaults are set - parms.strict = (parms.strict == null) ? false : parms.strict; - - // Pass the schema to the implementations validate - const validateParms = JSON.parse(JSON.stringify(parms)); - validateParms.schema = this.profileTypeSchema; - - // Log the API call - this.log.info(`Validating profile of type "${this.profileType}"...`); - - // Validate the profile object is correct for our usage here - does not include schema validation - this.validateProfileObject(parms.name, this.profileType, parms.profile); - - // Invoke the implementation - this.log.trace(`Invoking the profile validation implementation for profile "${parms.name}" of type "${this.profileType}".`); - - const response = await this.validateProfile(validateParms); - if (response == null) { - throw new ImperativeError({msg: `The profile manager implementation did NOT return a profile validate response.`}, - {tag: `Internal Profile Management Error`}); - } - - return response; - } - - /** - * Merge two profiles together. Useful when updating existing profiles with a few new - * fields, for example. - * @param {IProfile} oldProfile - the old profile, fields on this will have lower precedence - * @param {IProfile} newProfile - the new profile, fields on this will have higher precedence - * @returns {IProfile} - the merged profile - */ - public mergeProfiles(oldProfile: IProfile, newProfile: IProfile): IProfile { - const DeepMerge = require("deepmerge"); - // clone both profiles while merging so that the originals are not modified - const mergedProfile = DeepMerge(JSON.parse(JSON.stringify(oldProfile)), JSON.parse(JSON.stringify(newProfile))); - - // there can only be one dependency per type, - // but it's possible that the user only wants to - // update one of the dependencies, and keep dependencies of other types - // so we will allow merging of the dependencies field - // but will double check that no duplicates have been created - if (!(mergedProfile.dependencies == null) && !(newProfile.dependencies == null) - && newProfile.dependencies.length > 0) { - const markForDeletionKey = "markedForDelete"; - for (const newDependency of newProfile.dependencies) { - for (const mergedDependency of mergedProfile.dependencies) { - if (mergedDependency.type === newDependency.type && - mergedDependency.name !== newDependency.name) { - this.log.debug("Deleting dependency from old profile which was overridden " + - "by the new dependency of name %s", - newDependency.name); - mergedDependency[markForDeletionKey] = true; - } - } - } - mergedProfile.dependencies = mergedProfile.dependencies.filter((dependency: IProfileDependency) => { - - return !(dependency as any)[markForDeletionKey]; - }); - } - // we like the merging functionality for most things, but - // if we merge array type profile fields, then users will not be able to update array type - // fields through the CLI. So instead we will take array fields from the new type verbatim - // we'll use this helper to search through - const DataObjectParser = require("dataobject-parser"); - const findArrayFields = (property: any, propertyPath: string) => { - if (Array.isArray(property) && !(typeof property === 'string')) { - const newProfileProperty = new DataObjectParser(newProfile).get(propertyPath); - - // does the array type property appear on the newer profile - if (!(newProfileProperty == null)) { - // if so, wipe out the merged array with the value from the newer profile - this.log.debug("Replacing array type profile field \"%s\" with new value", propertyPath); - new DataObjectParser(mergedProfile).set(propertyPath, newProfileProperty); - } - } else if (!(typeof property === 'string')) { - for (const childPropertyName of Object.keys(property)) { - // object.keys returns array indices as well, - // so we won't recursively call our helper if - // the property name is just a number - const propertyNameIsArrayIndex = /^[0-9]+$/.test(childPropertyName); - if (!propertyNameIsArrayIndex) { - const newPropertyPath = propertyPath + "." + childPropertyName; - this.log.debug("Searching for array properties to replace in the field %s", newPropertyPath); - findArrayFields(property[childPropertyName], newPropertyPath); - } - } - } - }; - for (const propertyName of Object.keys(mergedProfile)) { - if (propertyName !== "dependencies") { - findArrayFields(mergedProfile[propertyName], propertyName); - } - } - return mergedProfile; - } - - /** - * Deletes a profile from disk. Ensures that the parameters are correct and removes the profile. If the profile is listed as a dependency of - * other profiles it will NOT delete the profile unless "rejectIfDependency" is set to false. - * @template D - * @param {IDeleteProfile} parms - See the interface for details - * @returns {Promise} - The promise that is fulfilled with the response object (see interface for details) or rejected - * with an Imperative Error. - * @memberof AbstractProfileManager - */ - public async delete(parms: D): Promise { - // Validate that the delete parms are valid - ImperativeExpect.toNotBeNullOrUndefined(parms, - `A delete was requested for profile type "${this.profileType}", but no parameters were specified.`); - ImperativeExpect.keysToBeDefinedAndNonBlank(parms, ["name"], - `A delete was requested for profile type "${this.profileType}", but the name specified is undefined or blank.`); - - // Ensure defaults are set - parms.rejectIfDependency = (parms.rejectIfDependency == null) ? true : parms.rejectIfDependency; - - // Log the API call - this.log.info(`Deleting profile "${parms.name}" of type "${this.profileType}"...`); - - // Check if the profile exists before continuing - if (this.locateExistingProfile(parms.name) == null) { - const msg: string = `Profile "${parms.name}" of type "${this.profileType}" does not exist.`; - this.log.error(msg); - throw new ImperativeError({msg}); - } - - // If specified, reject the delete if this profile is listed as dependency for another profile (of any type) - if (parms.rejectIfDependency) { - this.log.trace(`Reject if dependency was specified, loading all profiles to check if "${parms.name}" of type ` + - `"${this.profileType}" is a dependency.`); - const allProfiles = await this.loadAll({ noSecure: true }); - this.log.trace(`All profiles loaded (for dependency check).`); - const flatten = ProfileUtils.flattenDependencies(allProfiles); - const dependents: IProfile[] = this.isDependencyOf(flatten, parms.name); - if (dependents.length > 0) { - let depList: string = ""; - for (const dep of dependents) { - depList += ("\n" + `Name: "${dep.name}" Type: "${dep.type}"`); - } - const msg: string = `The profile specified for deletion ("${parms.name}" of type ` + - `"${this.profileType}") is marked as a dependency for profiles:` + depList; - throw new ImperativeError({msg}); - } - } - - this.log.trace(`Invoking implementation to delete profile "${parms.name}" of type "${this.profileType}".`); - const response = await this.deleteProfile(parms); - if (response == null) { - throw new ImperativeError({msg: `The profile manager implementation did NOT return a profile delete response.`}, - {tag: `Internal Profile Management Error`}); - } - - // If the meta file exists - read to check if the name of the default profile is the same as - // the profile that was deleted. If so, reset it to null. - if (this.locateExistingProfile(this.constructMetaName())) { - const meta = this.readMeta(this.constructFullProfilePath(this.constructMetaName())); - if (meta.defaultProfile === parms.name) { - this.log.debug(`Profile deleted was the default. Clearing the default profile for type "${this.profileType}".`); - this.clearDefault(); - response.defaultCleared = true; - } - } - - return response; - } - - /** - * Update the profile - The action performed is dictacted by the implementation of the Abstract manager. - * @template U - * @param {IUpdateProfile} parms - See the interface for details - * @returns {Promise} - The promise that is fulfilled with the response object (see interface for details) or rejected - * with an Imperative Error. - * @memberof AbstractProfileManager - */ - public async update(parms: U): Promise { - // Validate the input parameters are correct - ImperativeExpect.toNotBeNullOrUndefined(parms, - `An update for a profile of type "${this.profileType}" was requested, but no parameters were specified.`); - ImperativeExpect.keysToBeDefinedAndNonBlank(parms, ["name"], - `An update for a profile of type "${this.profileType}" was requested, but no name was specified.`); - - // Log the API call - this.log.info(`Updating profile "${parms.name}" of type "${this.profileType}"...`); - - // Invoke the implementation - this.log.trace(`Invoking update profile implementation for profile "${parms.name}" of type "${this.profileType}".`); - const response = await this.updateProfile(parms); - if (response == null) { - throw new ImperativeError({msg: `The profile manager implementation did NOT return a profile update response.`}, - {tag: `Internal Profile Management Error`}); - } - - return response; - } - - /** - * Sets the default profile for the profile managers type. - * @param {string} name - The name of the new default - * @returns {string} - The response string (or an error is thrown if the request cannot be completed); - * @memberof AbstractProfileManager - */ - public setDefault(name: string): string { - // Log the API call - this.log.info(`Set default API invoked. Setting "${name}" as default for type "${this.profileType}".`); - - // Construct the path to the profile that we are to set as the default for this type - const profileLocation: string = this.locateExistingProfile(name); - - // Find the meta profile - it may NOT exists - this is OK - will be created - let metaFilePath: string = this.locateExistingProfile(this.constructMetaName()); - - // Read the meta profile OR construct a new profile if it does NOT exist - let meta: IMetaProfile; - if (profileLocation) { - if (metaFilePath) { - this.log.trace(`The meta file exists for type "${this.profileType}". Reading meta...`); - meta = this.readMeta(metaFilePath); - this.log.trace(`Setting default in the meta file for type ${this.profileType}.`); - this.setDefaultInMetaObject(meta, name); - } else { - this.log.info(`The meta file does NOT exist for type "${this.profileType}", ` + - `writing the meta file and default profile ("${name}")`); - metaFilePath = this.constructFullProfilePath(this.constructMetaName()); - meta = { - defaultProfile: name, - configuration: this.profileTypeConfiguration - }; - } - - // Write the meta file to disk - this.log.info(`Writing the updated meta file to disk. Default: ${meta.defaultProfile}`); - ProfileIO.writeMetaFile(meta, metaFilePath); - } else { - const msg: string = `Cannot update default profile for type "${this.profileType}". ` + - `The profile name specified ("${name}") does not exist. ` + - `Please create before attempting to set the default.`; - this.log.error(msg); - // The profile name specified does NOT actually exist. This is an error. - throw new ImperativeError({msg}); - } - - return `Default profile for type "${this.profileType}" set to "${name}".`; - } - - /** - * Clears the default profile for the profile managers type. - * @returns {string} - The response string (or an error is thrown if the request cannot be completed); - * @memberof AbstractProfileManager - */ - public clearDefault(): string { - // Log the API call - this.log.info(`Clear default API invoked for type "${this.profileType}".`); - - // Find the meta profile - it may NOT exists - this is OK - will be created - let metaFilePath: string = this.locateExistingProfile(this.constructMetaName()); - - // Read the meta profile OR construct a new profile if it does NOT exist - let meta: IMetaProfile; - if (metaFilePath) { - this.log.trace(`The meta file exists for type "${this.profileType}". Reading meta...`); - meta = this.readMeta(metaFilePath); - this.log.trace(`Clearing default in the meta file for type ${this.profileType}.`); - this.setDefaultInMetaObject(meta, null); - } else { - this.log.info(`The meta file does NOT exist for type "${this.profileType}", ` + - `writing the meta file without a default profile`); - metaFilePath = this.constructFullProfilePath(this.constructMetaName()); - meta = { - defaultProfile: null, - configuration: this.profileTypeConfiguration - }; - } - - // Write the meta file to disk - this.log.info(`Writing the updated meta file to disk. Default: ${meta.defaultProfile}`); - ProfileIO.writeMetaFile(meta, metaFilePath); - - return `Default profile for type "${this.profileType}" cleared.`; - } - - /** - * Returns the default profile name for this "type" or "undefined" if no default is set. - * @returns {string} - The default profile name or undefined. - * @memberof AbstractProfileManager - */ - public getDefaultProfileName(): string { - const metaFile: string = this.locateExistingProfile(this.constructMetaName()); - let defaultName: string; - if (metaFile == null) { - return undefined; - } - - let meta: IMetaProfile; - try { - meta = this.readMeta(metaFile); - defaultName = meta.defaultProfile; - } catch (err) { - throw new ImperativeError({ - msg: `Error reading "${this.profileType}" meta file: ${err.message}.`, - additionalDetails: err - }); - } - - return defaultName; - } - - /** - * Load all profiles - the behavior is dictated by the implementation. - * @abstract - * @param {ILoadAllProfiles} [parms] - the load parameters - See interface for details - * @returns {Promise} - The list of profiles when the promise is fulfilled or rejected with an ImperativeError. - * @memberof AbstractProfileManager - */ - public abstract loadAll(parms?: ILoadAllProfiles): Promise; - - /** - * Save profile - performs the profile save according to the implementation - invoked when all parameters are valid - * (according the abstract manager). - * @protected - * @abstract - * @param {ISaveProfile} parms - See interface for details - * @returns {Promise} - The promise fulfilled with response or rejected with an ImperativeError. - * @memberof AbstractProfileManager - */ - protected abstract saveProfile(parms: ISaveProfile): Promise; - - /** - * Save profile - performs the profile load according to the implementation - invoked when all parameters are valid - * (according the abstract manager). - * @protected - * @abstract - * @param {ILoadProfile} parms - See interface for details - * @returns {Promise} - The promise fulfilled with response or rejected with an ImperativeError. - * @memberof AbstractProfileManager - */ - protected abstract loadProfile(parms: ILoadProfile): Promise; - - /** - * Delete profile - performs the profile delete according to the implementation - invoked when all parameters are valid - * (according the abstract manager). - * @protected - * @abstract - * @param {IDeleteProfile} parms - See interface for details - * @returns {Promise} - The promise fulfilled with response or rejected with an ImperativeError. - * @memberof AbstractProfileManager - */ - protected abstract deleteProfile(parms: IDeleteProfile): Promise; - - /** - * Validate profile - performs the profile validation according to the implementation - invoked when all parameters are valid - * (according the abstract manager). - * @protected - * @abstract - * @param {IValidateProfileWithSchema} parms - See interface for details - * @returns {Promise} - The promise fulfilled with response or rejected with an ImperativeError. - * @memberof AbstractProfileManager - */ - protected abstract validateProfile(parms: IValidateProfileWithSchema): Promise; - - /** - * Update profile - performs the profile update according to the implementation - invoked when all parameters are valid - * (according the abstract manager). - * @protected - * @abstract - * @param {IUpdateProfile} parms - See interface for details - * @returns {Promise} - The promise fulfilled with response or rejected with an ImperativeError. - * @memberof AbstractProfileManager - */ - protected abstract updateProfile(parms: IUpdateProfile): Promise; - - /** - * Load a profiles dependencies - dictacted by the implementation. - * @protected - * @abstract - * @param {string} name - the name of the profile to load dependencies for - * @param {IProfile} profile - The profile to load dependencies for. - * @param {boolean} failNotFound - True to fail "not found" errors - * @returns {Promise} - The promise fulfilled with response or rejected with an ImperativeError. - * @memberof AbstractProfileManager - */ - protected abstract loadDependencies(name: string, profile: IProfile, failNotFound: boolean): Promise; - - /** - * Invokes the profile IO method to delete the profile from disk. - * @protected - * @param {string} name - The name of the profile to delete. - * @returns {string} - The path where the profile was. - * @memberof AbstractProfileManager - */ - protected deleteProfileFromDisk(name: string): string { - const profileFullPath: string = this.locateExistingProfile(name); - ProfileIO.deleteProfile(name, profileFullPath); - return profileFullPath; - } - - /** - * Performs basic validation of a profile object - ensures that all fields are present (if required). - * @protected - * @param name - the name of the profile to validate - * @param type - the type of profile to validate - * @param {IProfile} profile - The profile to validate. - * @memberof AbstractProfileManager - */ - protected validateProfileObject(name: string, type: string, profile: IProfile) { - // Throw an error on type mismatch - if the profile manager type does not match the input profile - ImperativeExpect.toBeEqual(type, this.profileType, - `The profile passed on the create indicates a type ("${type}") that differs from ` + - `the type specified on this instance of the profile manager ("${this.profileType}").`); - - // Ensure that the profile name is specified and non-blank - ImperativeExpect.toBeDefinedAndNonBlank(name, "name", - `The profile passed does not contain a name (type: "${this.profileType}") OR the name property specified is ` + - `not of type "string".`); - - // Ensure that the profile name passed does NOT match the meta profile name - ImperativeExpect.toNotBeEqual(name, this.profileTypeMetaFileName, - `You cannot specify "${name}" as a profile name. ` + - `This profile name is reserved for internal Imperative usage.`); - - - // Validate the dependencies specification - if (!(profile.dependencies == null)) { - ImperativeExpect.keysToBeAnArray(profile, false, ["dependencies"], `The profile passed ` + - `(name "${name}" of type "${type}") has dependencies as a property, ` + - `but it is NOT an array (ill-formed)`); - - for (const dep of profile.dependencies) { - - // check for name on the dependency - ImperativeExpect.keysToBeDefinedAndNonBlank(dep, ["name"], `The profile passed ` + - `(name "${name}" of type "${type}") has dependencies as a property, ` + - `but an entry does not contain "name".`); - - // check for name on the dependency - ImperativeExpect.keysToBeDefinedAndNonBlank(dep, ["type"], `The profile passed ` + - `(name "${name}" of type "${type}") has dependencies as a property, ` + - `but an entry does not contain "type".`); - } - } - } - - /** - * Validates the profile against the schema for its type and reports and errors located. - * @protected - * @param name - the name of the profile to validate - * @param {IProfile} profile - The profile to validate. - * @param {boolean} [strict=false] - Set to true to enable the "ban unknown properties" specification of the JSON schema spec. In other words, - * prevents profiles with "unknown" or "not defined" proeprties according to the schema document. - * @memberof AbstractProfileManager - */ - protected validateProfileAgainstSchema(name: string, profile: IProfile, strict = false) { - - - // Instance of the validator - const validator = new SchemaValidator(); - - // don't make the user specify this internal field of "dependencies" - // they specify the dependencies on their profile config object, - // and the profile manager will construct them there - const schemaWithDependencies = JSON.parse(JSON.stringify(this.profileTypeSchema)); // copy the schema without modifying - // const dependencyProperty: IProfileProperty = { - // type: "array", - // items: { - // description: "The dependencies", - // type: "object", - // properties: { - // type: { - // description: "The type of dependent profile.", - // type: "string" - // }, - // name: { - // description: "The name of the dependent profile.", - // type: "string" - // }, - // } - // } - // }; - - // If strict mode is requested, then we will remove name and type (because they are inserted by the manager) and - // set the additional properties flag false, which, according to the JSON schema specification, indicates that - // no unknown properties should be present on the document. - if (strict || (!(schemaWithDependencies.additionalProperties == null) && schemaWithDependencies.additionalProperties === false)) { - schemaWithDependencies.additionalProperties = false; - } - - // TODO - @ChrisB, is this supposed to be commented out? - // schemaWithDependencies.dependencies = dependencyProperty; - const results = validator.validate(profile, schemaWithDependencies, {verbose: true}); - if (results.errors.length > 0) { - let validationErrorMsg: string = `Errors located in profile "${name}" of type "${this.profileType}":\n`; - for (const validationError of results.errors) { - // make the error messages more human readable - const property = validationError.property.replace("instance.", "") - .replace(/^instance$/, "profile"); - validationErrorMsg += property + " " + validationError.message + "\n"; - } - throw new ImperativeError({msg: validationErrorMsg, additionalDetails: results}); - } - } - - /** - * Constructs the full path to the profile of the managers "type". - * @protected - * @param {string} name - The profile name to construct the path - * @param {any} [type=this.profileType] - The type - normally the type specified in the manager. - * @returns {string} - The full profile directory. - * @memberof AbstractProfileManager - */ - protected constructFullProfilePath(name: string, type = this.profileType): string { - return nodePath.resolve(this.profileRootDirectory + "/" + type + "/" + name + AbstractProfileManager.PROFILE_EXTENSION); - } - - /** - * Locate the existing profile for the name specified. - * @protected - * @param {string} name - The profile to locate - * @returns {string} - The fully qualified path or undefined if not found. - * @memberof AbstractProfileManager - */ - protected locateExistingProfile(name: string): string { - const path: string = this.constructFullProfilePath(name); - return ProfileIO.exists(path); - } - - /** - * Standard load failed error message and Imperative Error. - * @protected - * @param {string} name - The name of the profile for which the load failed. - * @memberof AbstractProfileManager - */ - protected loadFailed(name: string) { - throw new ImperativeError({ - msg: `Profile "${name}" of type "${this.profileType}" does not exist.` - }); - } - - /** - * Checks if the profile object passed is "empty" - meaning it has no contents other than that type or name. - * A profile can only specify "dependencies", in the event that it is just acting as a "pointer" to another profile. - * @protected - * @param {IProfile} profile - The profile to check for "emptiness". - * @returns {boolean} True if the profile object is empty. - * @memberof AbstractProfileManager - */ - protected isProfileEmpty(profile: IProfile): boolean { - for (const key in profile) { - if (key === "type" || key === "name") { - continue; - } - if (Object.prototype.hasOwnProperty.call(profile, key)) { - return false; - } - } - return true; - } - - /** - * Loads a specific profile (by name). - * @protected - * @param {string} name - The name of the profile to load. - * @param {boolean} [failNotFound=true] - Specify false to ignore "not found" errors. - * @param {boolean} [loadDependencies=true] - Specify false to NOT load dependencies. - * @returns {Promise} - The promise to fulfill with the response OR reject with an ImperativeError - * @memberof AbstractProfileManager - */ - protected async loadSpecificProfile(name: string, failNotFound: boolean = true, loadDependencies: boolean = true): Promise { - // Ensure that the profile actually exists - const profileFilePath: string = this.locateExistingProfile(name); - - // If it doesn't exist and fail not found is false - if (profileFilePath == null && !failNotFound) { - return this.failNotFoundDefaultResponse(name); - } - - // Throw an error indicating that the load failed - if (profileFilePath == null) { - this.loadFailed(name); - } - - // Load the profile from disk - const profileContents = ProfileIO.readProfileFile(profileFilePath, this.profileType); - - // Insert the name and type - not persisted on disk - - try { - await this.validate({name, profile: profileContents}); - } catch (e) { - throw new ImperativeError({ - msg: `Profile validation error during load of profile "${name}" ` + - `of type "${this.profileType}". Error Details: ${e.message}`, - additionalDetails: e - }); - } - - // Construct the load response for this profile. - const loadResponse: IProfileLoaded = { - message: `Profile "${name}" of type "${this.profileType}" loaded successfully.`, - profile: profileContents, - type: this.profileType, - name, - failNotFound, - dependenciesLoaded: false, - dependencyLoadResponses: [] - }; - - // If requested, load the profile's dependencies - if (loadDependencies) { - const loadDependenciesResponse = await this.loadDependencies(name, profileContents, failNotFound); - if (!(loadDependenciesResponse == null) && loadDependenciesResponse.length > 0) { - loadResponse.dependenciesLoaded = true; - loadResponse.dependencyLoadResponses = loadDependenciesResponse; - } - } - - // Return the profile and dependencies to caller - return loadResponse; - } - - /** - * Validates a profiles contents against the required dependencies specified on the profile configuration type document. If the document - * indicates that a dependency is required and that dependency is missing from the input profile, an error is thrown. - * @private - * @param {IProfile} profile - The profile to validate dependency specs - * @memberof AbstractProfileManager - */ - protected validateRequiredDependenciesAreSpecified(profile: IProfile) { - if (!(this.profileTypeConfiguration.dependencies == null) && this.profileTypeConfiguration.dependencies.length > 0) { - const specifiedDependencies = profile.dependencies || []; - for (const dependencyConfig of this.profileTypeConfiguration.dependencies) { - // are required dependencies present in the profile? - if (dependencyConfig.required) { - let requiredDependencyFound = false; - for (const specifiedDependency of specifiedDependencies) { - if (specifiedDependency.type === dependencyConfig.type) { - requiredDependencyFound = true; - } - } - if (!requiredDependencyFound) { - throw new ImperativeError({ - msg: `Profile type "${this.profileType}" specifies a required dependency of type "${dependencyConfig.type}" ` + - `on the "${this.profileType}" profile type configuration document. A dependency of type "${dependencyConfig.type}" ` + - `was NOT listed on the input profile.` - }); - } - } - } - } - } - - - /** - * Checks if the profile (by name) is listed as a dependency of any other profile passed. The type of the profiled named is - * the type of the current manager object. - * @private - * @param {IProfileLoaded[]} profilesToSearch - The list of profiles to search for the dependency. - * @param {string} name - * @returns {IProfile[]} - * @memberof AbstractProfileManager - */ - private isDependencyOf(profilesToSearch: IProfileLoaded[], name: string): IProfile[] { - const foundAsDependencyIn: IProfile[] = []; - for (const prof of profilesToSearch) { - if (!(prof.profile.dependencies == null)) { - for (const dep of prof.profile.dependencies) { - if (name === dep.name && this.profileType === dep.type) { - foundAsDependencyIn.push(prof); - } - } - } - } - return foundAsDependencyIn; - } - - /** - * Protects a against an overwrite on a profile save (if requested). - * @private - * @param {string} name - The name of the profile to check for existance. - * @param {boolean} overwrite - False to protect against overwrite. - * @memberof AbstractProfileManager - */ - private protectAgainstOverwrite(name: string, overwrite: boolean) { - const file: string = this.locateExistingProfile(name); - if (!(file == null)) { - if (!overwrite) { - const errMsg: string = `Profile "${name}" of type "${this.profileType}" already ` + - `exists and overwrite was NOT specified.`; - throw new ImperativeError({ - msg: errMsg, - }); - } - } - } - - /** - * Builds the meta profile name for this type. Normally of the form "_meta". This method does NOT include the extension - * @private - * @param {any} [type=this.profileType] - The profile type - defaults to this manager's type. - * @returns {string} - * @memberof AbstractProfileManager - */ - private constructMetaName(type = this.profileType): string { - return type + AbstractProfileManager.META_FILE_SUFFIX; - } - - /** - * Create's the directory for this profile manager's type. - * @private - * @returns {string} - The directory created - * @memberof AbstractProfileManager - */ - private createProfileTypeDirectory(): string { - const profilePath: string = this.profileRootDirectory + "/" + this.profileType; - if (!ProfileIO.exists(profilePath)) { - ProfileIO.createProfileDirs(profilePath); - } - return profilePath + "/"; - } - - /** - * Set the default profile name in the meta profile for this type. - * @private - * @param {IMetaProfile} meta - The meta profile contents. - * @param {string} defaultProfileName - The name to set as default. - * @memberof AbstractProfileManager - */ - private setDefaultInMetaObject(meta: IMetaProfile, defaultProfileName: string) { - meta.defaultProfile = defaultProfileName; - } - - /** - * Construct the default response for the situation when a profile is not found (on a load/save/update/etc), but ignore not found is true. - * @private - * @param {string} name - The name of the profile that was not found - * @returns {IProfileLoaded} - The default response. - * @memberof AbstractProfileManager - */ - private failNotFoundDefaultResponse(name: string): IProfileLoaded { - this.log.debug(`Profile "${name}" of type "${this.profileType}" was not found, but failNotFound=False`); - return { - message: `Profile "${name}" of type "${this.profileType}" was not found, but the request indicated to ignore "not found" errors. ` + - `The profile returned is undefined.`, - type: this.profileType, - name, - failNotFound: false, - dependenciesLoaded: false, - dependencyLoadResponses: [] - }; - } - - /** - * Reads all configuration documents from the meta and collects all type configuration documents. - * @private - * @returns {T[]} - * @memberof AbstractProfileManager - */ - private collectAllConfigurations(): T[] { - const configs: T[] = []; - const types: string[] = ProfileIO.getAllProfileDirectories(this.profileRootDirectory); - for (const type of types) { - const meta = this.readMeta(this.constructFullProfilePath(this.constructMetaName(type), type)); - configs.push(meta.configuration); - } - return configs; - } - - /** - * Validate that the schema document passed is well formed for the profile manager usage. Ensures that the - * schema is not overloading reserved properties. - * @private - * @param {IProfileSchema} schema - The schema document to validate. - * @param type - the type of profile for the schema - defaults to the current type for this manager - * @memberof AbstractProfileManager - */ - private validateSchema(schema: IProfileSchema, type = this.profileType) { - ImperativeExpect.keysToBeDefined(schema, ["properties"], `The schema document supplied for the profile type ` + - `("${type}") does NOT contain properties.`); - ImperativeExpect.keysToBeUndefined(schema, ["properties.dependencies"], `The schema "properties" property ` + - `(on configuration document for type "${type}") contains "dependencies". ` + - `"dependencies" is must be supplied as part of the "type" configuration document (no need to formulate the dependencies ` + - `schema yourself).`); - } - - /** - * Validates the basic configuration document to ensure it contains all the proper fields - * @private - * @param {T} typeConfiguration - The type configuration document - * @memberof AbstractProfileManager - */ - private validateConfigurationDocument(typeConfiguration: T) { - ImperativeExpect.keysToBeDefinedAndNonBlank(typeConfiguration, ["type"], `The profile type configuration document for ` + - `"${typeConfiguration.type}" does NOT contain a type.`); - ImperativeExpect.keysToBeDefined(typeConfiguration, ["schema"], `The profile type configuration document for ` + - `"${typeConfiguration.type}" does NOT contain a schema.`); - this.validateSchema(typeConfiguration.schema, typeConfiguration.type); - if (!(typeConfiguration.dependencies == null)) { - ImperativeExpect.toBeAnArray(typeConfiguration.dependencies, - `The profile type configuration for "${typeConfiguration.type}" contains a "dependencies" property, ` + - `but it is not an array (ill-formed)`); - for (const dep of typeConfiguration.dependencies) { - ImperativeExpect.keysToBeDefinedAndNonBlank(dep, ["type"], "A dependency specified for the " + - "profile definitions did not contain a type."); - } - } - } - - /** - * Validate that a meta profile (one read from disk in particular) is valid. - * @private - * @param {IMetaProfile} meta - The meta profile to validate - * @param {string} [type=this.profileType] - The profile type of this meta file. - * @memberof AbstractProfileManager - */ - private validateMetaProfile(meta: IMetaProfile, type = this.profileType) { - ImperativeExpect.keysToBeDefined(meta, ["configuration"], `A meta profile of type "${type}", does NOT supply a configuration.`); - // ImperativeExpect.keysToBeDefined(meta, ["defaultProfile"], `A meta profile of type "${type}", does NOT supply a default profile.`); - } - - /** - * Read the meta profile and validate the contents. - * @private - * @param {string} path - path to the meta profile - * @param {string} [type=this.profileType] - The profile type - * @returns {IMetaProfile} - The meta profile read from disk. - * @memberof AbstractProfileManager - */ - private readMeta(path: string, type = this.profileType): IMetaProfile { - const meta = ProfileIO.readMetaFile(path); - this.validateMetaProfile(meta); - return meta; - } -} diff --git a/packages/imperative/src/profiles/src/abstract/AbstractProfileManagerFactory.ts b/packages/imperative/src/profiles/src/abstract/AbstractProfileManagerFactory.ts deleted file mode 100644 index 9d910391ae..0000000000 --- a/packages/imperative/src/profiles/src/abstract/AbstractProfileManagerFactory.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { AbstractProfileManager } from "./AbstractProfileManager"; -import { IProfileTypeConfiguration } from "../doc/config/IProfileTypeConfiguration"; -import { IProfileManagerFactory } from "../doc/api/IProfileManagerFactory"; -/** - * Abstract profile manager (implemented by imperative, etc.) - * @export - * @abstract - * @class AbstractProfileManagerFactory - * @implements {IProfileManagerFactory} - * @template T - */ -export abstract class AbstractProfileManagerFactory implements IProfileManagerFactory { - /** - * Returns and instance of the profile manager for the type specified. - * @abstract - * @param {string} type - the profile type - * @returns {AbstractProfileManager} - The manager - * @memberof AbstractProfileManagerFactory - */ - public abstract getManager(type: string): AbstractProfileManager; -} diff --git a/packages/imperative/src/profiles/src/constants/ProfilesConstants.ts b/packages/imperative/src/profiles/src/constants/ProfilesConstants.ts index fb035cf294..88c15f84b1 100644 --- a/packages/imperative/src/profiles/src/constants/ProfilesConstants.ts +++ b/packages/imperative/src/profiles/src/constants/ProfilesConstants.ts @@ -13,10 +13,5 @@ * Constants used within the auto-generated profiles group */ export class ProfilesConstants { - public static readonly PROFILES_COMMAND_TYPE_KEY = "profileTypeIdentifier"; public static readonly PROFILES_OPTION_SECURELY_STORED = "managed by"; - public static readonly DEPRECATE_TO_CONFIG_INIT = "The 'config init' command"; - public static readonly DEPRECATE_TO_CONFIG_LIST = "The 'config list' command"; - public static readonly DEPRECATE_TO_CONFIG_EDIT = "Edit your Zowe V2 configuration"; - public static readonly DEPRECATE_TO_CONFIG_SET = "The 'config set' command"; } diff --git a/packages/imperative/src/profiles/src/doc/api/IProfileManagerFactory.ts b/packages/imperative/src/profiles/src/doc/api/IProfileManagerFactory.ts deleted file mode 100644 index cb13380dbb..0000000000 --- a/packages/imperative/src/profiles/src/doc/api/IProfileManagerFactory.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IProfileTypeConfiguration } from "../config/IProfileTypeConfiguration"; -import { AbstractProfileManager } from "../../abstract/AbstractProfileManager"; -/** - * Profile manager factory inteface - implemented by the abstract profile manager in this profiles - * package and created by Imperative and other packages that need to influence the way the profile manager - * is allocated, configured. - * @export - * @interface IProfileManagerFactory - * @template T - */ -export interface IProfileManagerFactory { - /** - * Returns an instance of the profile manager specific to the "type" passed - types are defined by Imeprative - * configuration/init - * @param {string} type - The profile type. - * @returns {AbstractProfileManager} - An instance of the profile manager. - * @memberof IProfileManagerFactory - */ - getManager(type: string): AbstractProfileManager; -} diff --git a/packages/imperative/src/profiles/src/doc/config/IProfileTypeConfiguration.ts b/packages/imperative/src/profiles/src/doc/config/IProfileTypeConfiguration.ts index 0a1bb86c31..a4777ba354 100644 --- a/packages/imperative/src/profiles/src/doc/config/IProfileTypeConfiguration.ts +++ b/packages/imperative/src/profiles/src/doc/config/IProfileTypeConfiguration.ts @@ -14,9 +14,9 @@ import { IProfileDependency } from "../definition/IProfileDependency"; /** * The profile "type" configuration document. Provides all configuration information for the "type". A profile - * "type" is an arbirarty (implementation defined) category used to isolate configuration documents, provide + * "type" is an arbitrary (implementation defined) category used to isolate configuration documents, provide * ease of configuration for complex CLIs (user only configures what they'll use), and allows the CLI to be - * extendable in an isolated fashion. See the "IProfile" and "BasicProfileManager" for more detailed profile info. + * extendable in an isolated fashion. See the "IProfile" for more detailed profile info. * @export * @interface IProfileTypeConfiguration */ @@ -46,6 +46,7 @@ export interface IProfileTypeConfiguration { * * @type {IProfileDependency[]} * @memberof IProfileTypeConfiguration + * @deprecated Only applies to V1 profiles. For team config, use nested profiles instead. */ dependencies?: IProfileDependency[]; /** @@ -55,6 +56,7 @@ export interface IProfileTypeConfiguration { * * @type {string} * @memberof IProfileTypeConfiguration + * @deprecated Only applies to V1 profiles. For team config, validate with JSON schema instead. */ validationPlanModule?: string; } diff --git a/packages/imperative/src/profiles/src/doc/index.ts b/packages/imperative/src/profiles/src/doc/index.ts index 2177e34d5e..2a83e06d9b 100644 --- a/packages/imperative/src/profiles/src/doc/index.ts +++ b/packages/imperative/src/profiles/src/doc/index.ts @@ -9,8 +9,6 @@ * */ -export * from "./api/IProfileManagerFactory"; - export * from "./config/IProfileTypeConfiguration"; export * from "./definition"; diff --git a/packages/imperative/src/profiles/src/doc/parms/IDeleteProfile.ts b/packages/imperative/src/profiles/src/doc/parms/IDeleteProfile.ts deleted file mode 100644 index 90782c6572..0000000000 --- a/packages/imperative/src/profiles/src/doc/parms/IDeleteProfile.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -/** - * Parameters to the profile manager "delete" API. - * @export - * @interface IDeleteProfile - */ -export interface IDeleteProfile { - /** - * The name of the profile to delete - the type is specified by the current manager object. - * @type {string} - * @memberof IDeleteProfile - */ - name: string; - /** - * If true, rejects the deletion of the profile if it is found to be a dependency of another profile. - * @type {boolean} - * @memberof IDeleteProfile - */ - rejectIfDependency?: boolean; -} diff --git a/packages/imperative/src/profiles/src/doc/parms/ILoadAllProfiles.ts b/packages/imperative/src/profiles/src/doc/parms/ILoadAllProfiles.ts deleted file mode 100644 index 97ca5b014c..0000000000 --- a/packages/imperative/src/profiles/src/doc/parms/ILoadAllProfiles.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -/** - * Optional parameters to profile manager load all profiles - * @export - * @interface ILoadAllProfiles - */ -export interface ILoadAllProfiles { - /** - * If true, do not load secure fields - * @type {boolean} - * @memberof ILoadAllProfiles - */ - noSecure?: boolean; - /** - * If true, loads only the profiles of the current instance of the profile - * managers "type" - specified when allocating the profile manager. - * @type {boolean} - * @memberof ILoadAllProfiles - */ - typeOnly?: boolean; -} diff --git a/packages/imperative/src/profiles/src/doc/parms/ILoadProfile.ts b/packages/imperative/src/profiles/src/doc/parms/ILoadProfile.ts deleted file mode 100644 index 36f2db6223..0000000000 --- a/packages/imperative/src/profiles/src/doc/parms/ILoadProfile.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -/** - * Profile Manager "loadProfile" input parameters. Indicates which profile to load (named or default) and if - * not finding the profile should be considered and error, etc. - * @export - * @interface ILoadProfile - */ -export interface ILoadProfile { - /** - * The name of the profile to load - ignored if "loadDefault" is true - the type is indicated by the - * instance of the instantiated profile manager. - * @type {string} - * @memberof ILoadProfile - */ - name?: string; - /** - * Load the default profile for the "type" specified in the profile manager instance - if specified, "name" is - * ignored. - * @type {boolean} - * @memberof ILoadProfile - */ - loadDefault?: boolean; - /** - * Under "normal" circumstances, attempting to load a non-existant profile is an error, however, you may indicate - * that the profile manager should treat this as a "soft" failure, meaning the promise for the load API will - * be fulfilled - with the appropriate status message and no profile. - * @type {boolean} - * @memberof ILoadProfile - */ - failNotFound?: boolean; - /** - * Profiles can have dependencies. Specify "false" if you want to avoid loading the dependencies of this profile. - * True is the default. - * @type {boolean} - * @memberof ILoadProfile - */ - loadDependencies?: boolean; - /** - * If true, fields that indicate "secure" are not loaded. The properties will still be present in the profiles - * loaded with a value of "securely_stored". - * @type {boolean} - * @memberof ILoadProfile - */ - noSecure?: boolean; -} diff --git a/packages/imperative/src/profiles/src/doc/parms/IProfileManager.ts b/packages/imperative/src/profiles/src/doc/parms/IProfileManager.ts index c4f4ac6cb9..df8e1f695e 100644 --- a/packages/imperative/src/profiles/src/doc/parms/IProfileManager.ts +++ b/packages/imperative/src/profiles/src/doc/parms/IProfileManager.ts @@ -19,16 +19,6 @@ import { Logger } from "../../../../logger"; import { IProfileTypeConfiguration } from "../config/IProfileTypeConfiguration"; export interface IProfileManager { - /** - * The profiles directory (normally obtained from the Imperative config). The profile root directory contains - * a list of type directories, within each will be the profiles of that type and the meta file. The meta file - * for a type contains the default specifications and the profile type configuration document. Use the "initialize" - * API method on the Profile Manager to create the appropriate structure based on your configuration documents. - * - * @type {string} - * @memberof IProfileManager - */ - profileRootDirectory: string; /** * The profile type for this manager - the configuration document for the type can either be supplied on the * "typeConfigurations" property on this object OR the mananger will attempt to extract it from the profile @@ -61,12 +51,6 @@ export interface IProfileManager { */ typeConfigurations?: T[]; - /** - * Map of which profile types have been loaded so far, to avoid circular profile loads - * Used internally by profile manager classes - */ - loadCounter?: Map; - /** * Product display name of CLI * @type {string} diff --git a/packages/imperative/src/profiles/src/doc/parms/IProfileManagerInit.ts b/packages/imperative/src/profiles/src/doc/parms/IProfileManagerInit.ts deleted file mode 100644 index 0105606395..0000000000 --- a/packages/imperative/src/profiles/src/doc/parms/IProfileManagerInit.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IProfileTypeConfiguration } from "../config/IProfileTypeConfiguration"; -/** - * Parameters passed on the "basic profile manager" "initialize()" API. The initialization API creates the entire - * profile directory structure and persists the configuration documents for each type in their respective meta profile. - * The configuration documents are persisted for two reasons: - * - * 1) To help "external" invocations of the profile manager avoid having to provide the configuration documents. - * This makes constructing apps and editor extensions that depend on profiles much simpler and protects the - * profiles. - * - * 2) Ensures a consistency between versions and updates to the profile structure - we can compare the persisted - * profiles against the configuration documents supplied when Imperative is initialized. - * - * @export - * @interface IProfileManagerInit - */ -export interface IProfileManagerInit { - /** - * The full set of profile "type" configuration documents - Normally supplied by the CLI definition document. See - * the interface for full details. - * @type {IProfileTypeConfiguration[]} - * @memberof IProfileManagerInit - */ - configuration: IProfileTypeConfiguration[]; - /** - * The root directory for the profile manager - this is where all type directories will be initialized. The root is - * normally supplied on the configuration document for an Imperative CLI. - * @type {string} - * @memberof IProfileManagerInit - */ - profileRootDirectory: string; - /** - * If true, will re-initialize and profile type directories found. If false, any existing definitions/types/metas - * are not touched - Can be called during Imperative init with false, to ensure that nothing is overwritten, but - * additional types are added as supplied. - * @type {boolean} - * @memberof IProfileManagerInit - */ - reinitialize?: boolean; -} diff --git a/packages/imperative/src/profiles/src/doc/parms/ISaveProfile.ts b/packages/imperative/src/profiles/src/doc/parms/ISaveProfile.ts deleted file mode 100644 index 7d6219d55b..0000000000 --- a/packages/imperative/src/profiles/src/doc/parms/ISaveProfile.ts +++ /dev/null @@ -1,70 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IProfile } from "../definition/IProfile"; - -/** - * Parameters to the "save()" profile API. - * - * Note: This profile could contain the following additional arguments, - * which will only be kept in memory (for a short period of time) and NOT saved to a file. - * @type {string} username - The username to be securely saved to this profile. - * @type {string} password - The password for the username to be securely saved to this profile. - * - * @export - * @interface ISaveProfile - */ -export interface ISaveProfile { - /** - * The profile contents - must extend the IProfile interface to function properly with Imperative. The contents - * are always validated against the schema documents (and basic validation occurs) - * - * @type {IProfile} - * @memberof ISaveProfile - */ - profile: IProfile; - - /** - * The name of the profile to save - * - * @type {string} - * @memberof ISaveProfile - */ - name: string; - - /** - * The type of profile to save - * @type {string} - * @memberof ISaveProfile - */ - type: string; - - /** - * Set to true to update the default profile for the profile type. - * @type {boolean} - * @memberof ISaveProfile - */ - updateDefault?: boolean; - /** - * Set to true to overwrite an existing profile of the same name. If false, an error is thrown if the profile - * already exists. - * @type {boolean} - * @memberof ISaveProfile - */ - overwrite?: boolean; - - /** - * The argument to disable populating defaults - * @type {boolean} - * @memberof ISaveProfileFromCliArgs - */ - disableDefaults?: boolean; -} diff --git a/packages/imperative/src/profiles/src/doc/parms/ISaveProfileFromCliArgs.ts b/packages/imperative/src/profiles/src/doc/parms/ISaveProfileFromCliArgs.ts deleted file mode 100644 index d74ad59f2e..0000000000 --- a/packages/imperative/src/profiles/src/doc/parms/ISaveProfileFromCliArgs.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { Arguments } from "yargs"; -import { ISaveProfile } from "./ISaveProfile"; - -/** - * Parameters for creating a profile from command line arguments - normally invoked from a command handler that - * is pre-built by imperative. - * @export - * @interface ICreateProfileFromArgs - */ -export interface ISaveProfileFromCliArgs extends ISaveProfile { - /** - * The Yargs style arguments - supplied from the command invocation. - * @type {Arguments} - * @memberof ISaveProfileFromCliArgs - */ - args?: Arguments; -} diff --git a/packages/imperative/src/profiles/src/doc/parms/ISetDefaultProfile.ts b/packages/imperative/src/profiles/src/doc/parms/ISetDefaultProfile.ts deleted file mode 100644 index dd481c8ee6..0000000000 --- a/packages/imperative/src/profiles/src/doc/parms/ISetDefaultProfile.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -/** - * Parameters for the setDefault Profile Manager API. - * @export - * @interface ISetDefaultProfile - */ -export interface ISetDefaultProfile { - /** - * The name of the profile to set as the default (the type is indicated by the profile manager object). - * @type {string} - * @memberof ISetDefaultProfile - */ - name: string; -} diff --git a/packages/imperative/src/profiles/src/doc/parms/IUpdateProfile.ts b/packages/imperative/src/profiles/src/doc/parms/IUpdateProfile.ts deleted file mode 100644 index 906743a780..0000000000 --- a/packages/imperative/src/profiles/src/doc/parms/IUpdateProfile.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IProfile } from "../definition/IProfile"; - -/** - * Parameters to update a profile - The basic implementation simply overwrites the existing profile with the new - * contents specified, unless merge is true, and the contents of the old profile are merged with the contents from - * the update profile. - * - * Note: This profile could contains the following additional arguments, - * which will only be kept in memory (for a short period of time) and NOT saved to a file. - * @type {string} username - The username to be securely saved to this profile. - * @type {string} password - The password for the username to be securely saved to this profile. - * - * @export - * @interface IUpdateProfile - */ -export interface IUpdateProfile { - /** - * The name of the profile to update. - * @type {string} - * @memberof IUpdateProfile - */ - name?: string; - /** - * Should the contents of the new profile be merged with the contents of the old one? - * @type {boolean} - */ - merge?: boolean; - /** - * The contents of the profile for the update - if merge is NOT specified, simply overwrites the existing - * profile with the contents specified here. - * @type {IProfile} - * @memberof IUpdateProfile - */ - profile?: IProfile; -} diff --git a/packages/imperative/src/profiles/src/doc/parms/IUpdateProfileFromCliArgs.ts b/packages/imperative/src/profiles/src/doc/parms/IUpdateProfileFromCliArgs.ts deleted file mode 100644 index e10e345d3c..0000000000 --- a/packages/imperative/src/profiles/src/doc/parms/IUpdateProfileFromCliArgs.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IUpdateProfile } from "./IUpdateProfile"; -import { Arguments } from "yargs"; -/** - * TODO - wasn't this moved??? - * @export - * @interface IUpdateProfileFromCliArgs - * @extends {IUpdateProfile} - */ -export interface IUpdateProfileFromCliArgs extends IUpdateProfile { - args: Arguments; -} diff --git a/packages/imperative/src/profiles/src/doc/parms/IValidateProfile.ts b/packages/imperative/src/profiles/src/doc/parms/IValidateProfile.ts deleted file mode 100644 index 4665f09822..0000000000 --- a/packages/imperative/src/profiles/src/doc/parms/IValidateProfile.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IProfile } from "../definition/IProfile"; - -/** - * Parameters to the "validate()" profile manager APIs. Validates a profile structure (basic and schema) - * @export - * @interface IValidateProfile - */ -export interface IValidateProfile { - /** - * The name of the profile to validate. - * @type {string} - * @memberof IValidateProfile - */ - name: string; - /** - * The profile contents to validate. - * @type {IProfile} - * @memberof IValidateProfile - */ - profile: IProfile; - /** - * Specify true to indicate the "ban unknown properties" specification of JSON schema. Meaning, any properties - * found on the input profile that are NOT specified on the schema cause the validation to fail. - * @type {boolean} - * @memberof IValidateProfile - */ - strict?: boolean; -} diff --git a/packages/imperative/src/profiles/src/doc/parms/IValidateProfileForCLI.ts b/packages/imperative/src/profiles/src/doc/parms/IValidateProfileForCLI.ts deleted file mode 100644 index 3305d1c332..0000000000 --- a/packages/imperative/src/profiles/src/doc/parms/IValidateProfileForCLI.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IValidateProfileWithSchema } from "./IValidateProfileWithSchema"; - -/** - * Input to the "validateProfile" internal API. Indicates the schema document to be used for the validation. - * Used with the CLI Profile manager - validation is skipped until the profile is fully built - * @export - * @interface IValidateProfileWithSchema - * @extends {IValidateProfile} - */ -export interface IValidateProfileForCLI extends IValidateProfileWithSchema { - /** - * If false/undefined, validation will be skipped until validation - * is called again with "true" (indicating that the profile building is complete) - */ - readyForValidation: boolean; -} diff --git a/packages/imperative/src/profiles/src/doc/parms/IValidateProfileWithSchema.ts b/packages/imperative/src/profiles/src/doc/parms/IValidateProfileWithSchema.ts deleted file mode 100644 index d7c384d6e8..0000000000 --- a/packages/imperative/src/profiles/src/doc/parms/IValidateProfileWithSchema.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IProfileSchema } from "../definition/IProfileSchema"; -import { IValidateProfile } from "./IValidateProfile"; - -/** - * Input to the "validateProfile" internal API. Indicates the schema document to be used for the validation. - * @export - * @interface IValidateProfileWithSchema - * @extends {IValidateProfile} - */ -export interface IValidateProfileWithSchema extends IValidateProfile { - /** - * The profile JSON schema document. - * @type {IProfileSchema} - * @memberof IValidateProfileWithSchema - */ - schema: IProfileSchema; -} diff --git a/packages/imperative/src/profiles/src/doc/parms/index.ts b/packages/imperative/src/profiles/src/doc/parms/index.ts index e848e06353..6831ca13a7 100644 --- a/packages/imperative/src/profiles/src/doc/parms/index.ts +++ b/packages/imperative/src/profiles/src/doc/parms/index.ts @@ -9,16 +9,4 @@ * */ -export * from "./IDeleteProfile"; -export * from "./ILoadAllProfiles"; -export * from "./ILoadProfile"; export * from "./IProfileManager"; -export * from "./IProfileManagerInit"; -export * from "./ISaveProfile"; -export * from "./ISaveProfileFromCliArgs"; -export * from "./ISetDefaultProfile"; -export * from "./IUpdateProfile"; -export * from "./IUpdateProfileFromCliArgs"; -export * from "./IValidateProfile"; -export * from "./IValidateProfileForCLI"; -export * from "./IValidateProfileWithSchema"; diff --git a/packages/imperative/src/profiles/src/doc/response/IProfileDeleted.ts b/packages/imperative/src/profiles/src/doc/response/IProfileDeleted.ts deleted file mode 100644 index 8edf26611e..0000000000 --- a/packages/imperative/src/profiles/src/doc/response/IProfileDeleted.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -/** - * The success response to the profile "delete()" API. - * @export - * @interface IProfileDeleted - */ -export interface IProfileDeleted { - /** - * The path to the profile that was deleted. - * @type {string} - * @memberof IProfileDeleted - */ - path: string; - /** - * The message - for display purposes - e.g. The profile was successfully deleted. - * @type {string} - * @memberof IProfileDeleted - */ - message: string; - /** - * Specifies whether the default profile was cleared. - * @type {boolean} - * @memberof IProfileDeleted - */ - defaultCleared?: boolean; -} diff --git a/packages/imperative/src/profiles/src/doc/response/IProfileInitialized.ts b/packages/imperative/src/profiles/src/doc/response/IProfileInitialized.ts deleted file mode 100644 index 4fd1dd822b..0000000000 --- a/packages/imperative/src/profiles/src/doc/response/IProfileInitialized.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -/** - * Response to the Basic profile manager's initialize API - normally provided as an array to the caller indicating - * each profile type that was initialized. - * @export - * @interface IProfileInitialized - */ -export interface IProfileInitialized { - /** - * The message indicating that the profile type was initialized or re-initialized. - * @type {string} - * @memberof IProfileInitialized - */ - message: string; -} diff --git a/packages/imperative/src/profiles/src/doc/response/IProfileSaved.ts b/packages/imperative/src/profiles/src/doc/response/IProfileSaved.ts deleted file mode 100644 index d45bdb2e88..0000000000 --- a/packages/imperative/src/profiles/src/doc/response/IProfileSaved.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IProfile } from "../definition/IProfile"; -/** - * The success response to the profile "save()" API. - * @export - * @interface IProfileSaved - */ -export interface IProfileSaved { - /** - * The path that the new profile was written to - * @type {string} - * @memberof IProfileSaved - */ - path: string; - /** - * A message describing the result of the profile creation - for display purposes - * @type {string} - * @memberof IProfileSaved - */ - message: string; - /** - * True if the profile saved overwrote an existing profile of the same name/type. - * - * @type {boolean} - * @memberof IProfileSaved - */ - overwritten: boolean; - /** - * The contents of the profile saved. - * @type {IProfile} - * @memberof IProfileSaved - */ - profile?: IProfile; -} diff --git a/packages/imperative/src/profiles/src/doc/response/IProfileValidated.ts b/packages/imperative/src/profiles/src/doc/response/IProfileValidated.ts deleted file mode 100644 index f8ff020790..0000000000 --- a/packages/imperative/src/profiles/src/doc/response/IProfileValidated.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -/** - * The success response to the profile "validate()" APi. - * @export - * @interface IProfileValidated - */ -export interface IProfileValidated { - /** - * Message - for display purposes - e.g. The profile was updated. - * @type {string} - * @memberof IProfileValidated - */ - message: string; -} diff --git a/packages/imperative/src/profiles/src/doc/response/index.ts b/packages/imperative/src/profiles/src/doc/response/index.ts index 17dedc9510..48c60a0eb6 100644 --- a/packages/imperative/src/profiles/src/doc/response/index.ts +++ b/packages/imperative/src/profiles/src/doc/response/index.ts @@ -9,10 +9,4 @@ * */ -export * from "./IProfileDeleted"; -export * from "./IProfileInitialized"; export * from "./IProfileLoaded"; -export * from "./IProfileSaved"; -export * from "./IProfileUpdated"; -export * from "./IProfileValidated"; - diff --git a/packages/imperative/src/profiles/src/utils/ProfileIO.ts b/packages/imperative/src/profiles/src/utils/ProfileIO.ts deleted file mode 100644 index 41f7419d19..0000000000 --- a/packages/imperative/src/profiles/src/utils/ProfileIO.ts +++ /dev/null @@ -1,333 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ImperativeError } from "../../../error"; -import { ImperativeConfig } from "../../../utilities"; -import * as fs from "fs"; -import { IProfile } from "../doc/definition/IProfile"; -import { IMetaProfile } from "../doc/definition/IMetaProfile"; -import * as pathPackage from "path"; -import { IO } from "../../../io"; -import { IProfileTypeConfiguration } from "../doc/config/IProfileTypeConfiguration"; - -const readYaml = require("js-yaml"); -const writeYaml = require("yamljs"); - -/** - * Profile IO methods for writing/reading profiles to disk. The profile managers never invoke "fs" directly. - * All "fs" calls are wrapped here and errors are transformed to ImperativeError for error handling/flow throughout - * Imperative. - * - * @export - * @class ProfileIO - */ -export class ProfileIO { - /** - * The yamljs package requires you to indicate the depth for conversion to yaml. Set to max of 9999. - * @static - * @type {number} - * @memberof ProfileIO - */ - public static readonly MAX_YAML_DEPTH: number = 9999; - - /** - * Creates the full set of directories indicated by the path. Used to create the profile root directory and - * type directories. - * @static - * @param {string} path - The directory path to create - creates all necessary subdirectories. - * @memberof ProfileIO - */ - public static createProfileDirs(path: string) { - ProfileIO.crashInTeamConfigMode(); - try { - IO.createDirsSync(path); - } catch (err) { - throw new ImperativeError({ - msg: `An error occurred creating profile directory: "${path}". ` + - `Error Details: ${err.message}`, - additionalDetails: err - }, {tag: ProfileIO.ERROR_ID}); - } - } - - /** - * Read the profile meta file using Yaml "safeLoad" (ensures that no code executes, etc. during the load). The - * meta profile file for a type contains the default profile specification. The meta profile is ALWAYS in YAML - * format (controlled exclusively by the Imperative framework). - * @static - * @param {string} path - The path to the meta profile - * @returns {IMetaProfile} - The meta profile - * @memberof ProfileIO - */ - public static readMetaFile(path: string): IMetaProfile { - ProfileIO.crashInTeamConfigMode(); - - let meta: IMetaProfile; - try { - meta = readYaml.load(fs.readFileSync(path), "utf8"); - } catch (err) { - throw new ImperativeError({ - msg: `Error reading profile file ("${path}"). Error Details: ${err.message}`, - additionalDetails: err - }, {tag: ProfileIO.ERROR_ID}); - } - return meta; - } - - /** - * Accepts a profile object and writes the profile to the specified location (and optionally converts - * the profile to YAML format - the default for Imperative profiles). - * @static - * @param {string} fullFilePath - the fully qualified profile path, file, & extension. - * @param {IProfile} profile - the profile object to write to disk. - * @memberof ProfileIO - */ - public static writeProfile(fullFilePath: string, profile: IProfile): void { - ProfileIO.crashInTeamConfigMode(); - - try { - /** - * Write the YAML file - clone the object first and remove the name. Imperative will not persist the - * name within the profile (but needs it when loading/using). - */ - const profileCopy = JSON.parse(JSON.stringify(profile)); - delete profileCopy.name; - - /** - * If yaml = true, we will attempt to convert to yaml format before persisting. - */ - const writeProfile: any = writeYaml.stringify(profileCopy, ProfileIO.MAX_YAML_DEPTH); - - /** - * Attempt to write the profile - always encoded in utf-8 - */ - fs.writeFileSync(fullFilePath, writeProfile, {encoding: "utf8"}); - } catch (err) { - throw new ImperativeError({ - msg: `Profile IO Error: Error creating profile file ("${fullFilePath}"). Error Details: ${err.message}`, - additionalDetails: err.message - }); - } - } - - /** - * Delete the profile and ensure it is gone. - * @static - * @param {string} name - the profile object - really only used for error messages - * @param {string} fullFilePath - the full file path to delete - * @memberof ProfileIO - */ - public static deleteProfile(name: string, fullFilePath: string) { - ProfileIO.crashInTeamConfigMode(); - - try { - /** - * Attempt to remove the file and ensure that it was removed successfully - */ - fs.unlinkSync(fullFilePath); - if (fs.existsSync(fullFilePath)) { - const errorMsg: string = `The profile ${name} was unable to be deleted. ` + - `Please check the path indicated here and try to remove the profile manually: ${fullFilePath}`; - throw new ImperativeError({ - msg: errorMsg - }, {tag: ProfileIO.ERROR_ID}); - } - } catch (deleteErr) { - /** - * If an error occurred, rethrow if already instance of ImperativeError OR transform and throw - */ - if (deleteErr instanceof ImperativeError) { - throw deleteErr; - } else { - throw new ImperativeError({ - msg: `An unexpected profile delete error occurred for profile "${name}". ` + - `Error Details: ${deleteErr.message}.`, - additionalDetails: deleteErr - }, {tag: ProfileIO.ERROR_ID}); - } - } - } - - /** - * Checks if the file specified exists. - * @static - * @param {string} path - The file path - * @returns {string} - the path to the existing file or NULL if not found - * @memberof ProfileIO - */ - public static exists(path: string): string { - ProfileIO.crashInTeamConfigMode(); - - let found: string; - try { - found = (fs.existsSync(path)) ? path : undefined; - } catch (e) { - throw new ImperativeError({ - msg: `An error occurred checking for the existance of "${path}". Error Details: ${e.message}`, - additionalDetails: e - }, {tag: ProfileIO.ERROR_ID}); - } - return found; - } - - /** - * Converts the meta to yaml and writes to disk - * @static - * @param {IMetaProfile} meta - The meta profile contents to write to disk - * @param {string} path - The path to the meta profile - * @memberof ProfileIO - */ - public static writeMetaFile(meta: IMetaProfile, path: string) { - ProfileIO.crashInTeamConfigMode(); - - try { - const yamlString: any = writeYaml.stringify(meta, ProfileIO.MAX_YAML_DEPTH); - fs.writeFileSync(path, yamlString, {encoding: "utf8"}); - } catch (e) { - throw new ImperativeError({ - msg: `An error occurred converting and writing the meta profile to "${path}". ` + - `Error Details: ${e.message}`, - additionalDetails: e - }, {tag: ProfileIO.ERROR_ID}); - } - } - - /** - * Extracts the profile name from the file path/name - * @static - * @param {string} file - the file path to extract the profile name - * @param {string} ext - the extension of the file - * @returns {string} - the profile name - * @memberof ProfileIO - */ - public static fileToProfileName(file: string, ext: string): string { - ProfileIO.crashInTeamConfigMode(); - - file = pathPackage.basename(file); - return file.substring(0, file.lastIndexOf(ext)); - } - - /** - * Accepts the profiles root directory and returns all directories within. The directories within the root - * directory are all assumed to be profile type directories (potentially containing a meta file and profiles - * of that type). - * @static - * @param {string} profileRootDirectory - The profiles root directory to obtain all profiles from. - * @returns {string[]} - The list of profiles returned or a blank array - * @memberof ProfileIO - */ - public static getAllProfileDirectories(profileRootDirectory: string): string[] { - ProfileIO.crashInTeamConfigMode(); - - let names: string[] = []; - try { - names = fs.readdirSync(profileRootDirectory); - names = names.filter((name) => { - // only return directories, not files - const stats = fs.statSync(pathPackage.join(profileRootDirectory, name)); - return stats.isDirectory(); - }); - } catch (e) { - throw new ImperativeError({ - msg: `An error occurred attempting to read all profile directories from "${profileRootDirectory}". ` + - `Error Details: ${e.message}`, - additionalDetails: e - }, {tag: ProfileIO.ERROR_ID}); - } - return names; - } - - /** - * Accepts the profile directory location for a type, reads all filenames, and returns a list of - * profile names that are present within the directory (excluding the meta profile) - * @static - * @param {string} profileTypeDir - The directory for the type - * @param {string} ext - the extension for the profile files (normally YAML) - * @param {string} metaNameForType - the meta name for this type - * @returns {string[]} - A list of all profile names (without path/ext) - * @memberof ProfileIO - */ - public static getAllProfileNames(profileTypeDir: string, ext: string, metaNameForType: string): string[] { - ProfileIO.crashInTeamConfigMode(); - - const names: string[] = []; - try { - let profileFiles = fs.readdirSync(profileTypeDir); - profileFiles = profileFiles.filter((file) => { - const fullFile = pathPackage.resolve(profileTypeDir, file); - const isYamlFile = fullFile.length > ext.length && fullFile.substring( - fullFile.length - ext.length) === ext; - return isYamlFile && ProfileIO.fileToProfileName(fullFile, ext) !== metaNameForType; - }); - for (const file of profileFiles) { - names.push(ProfileIO.fileToProfileName(file, ext)); - } - } catch (e) { - throw new ImperativeError({ - msg: `An error occurred attempting to read all profile names from "${profileTypeDir}". ` + - `Error Details: ${e.message}`, - additionalDetails: e - }, {tag: ProfileIO.ERROR_ID}); - } - return names; - } - - /** - * Read a profile from disk. Profiles are always assumed to be YAML (YAML "safeLoad" is invoked to perform the load). - * @static - * @param {string} filePath - Path to the profile. - * @param {string} type - The profile type; used to populate the "type" in the profile object (type property not persisted on disk). - * @returns {IProfile} - The profile object. - * @memberof ProfileIO - */ - public static readProfileFile(filePath: string, type: string): IProfile { - ProfileIO.crashInTeamConfigMode(); - - let profile: IProfile; - try { - profile = readYaml.load(fs.readFileSync(filePath, "utf8")); - } catch (err) { - throw new ImperativeError({ - msg: `Error reading profile file ("${filePath}"). Error Details: ${err.message}`, - additionalDetails: err - }, {tag: ProfileIO.ERROR_ID}); - } - return profile; - } - - /** - * Crash if we detect that we are running in team-config mode. - * You should not be able to operate on old-school profiles - * when you are in team-config mode. Give a meaningful - * message as part of our crash. - */ - private static crashInTeamConfigMode() { - if (ImperativeConfig.instance.config?.exists) { - try { - throw new Error("A Zowe V1 profile operation was attempted with a Zowe V2 configuration in use."); - } catch (err) { - throw new ImperativeError({ - msg: err.message, - additionalDetails: err.stack, - }, {tag: ProfileIO.ERROR_ID}); - } - } - } - - /** - * Error IO tag for Imperative Errors - * @private - * @static - * @type {string} - * @memberof ProfileIO - */ - private static ERROR_ID: string = "Profile IO Error"; -} diff --git a/packages/imperative/src/profiles/src/utils/ProfileUtils.ts b/packages/imperative/src/profiles/src/utils/ProfileUtils.ts index 3005177057..408ad49e10 100644 --- a/packages/imperative/src/profiles/src/utils/ProfileUtils.ts +++ b/packages/imperative/src/profiles/src/utils/ProfileUtils.ts @@ -17,6 +17,7 @@ import * as nodePath from "path"; * Set of static utility methods to assist with creating profile option names from profile types, constructing the * root directory, reforming responses for different purposes, etc. * + * @internal * @export * @class ProfileUtils */ @@ -46,7 +47,7 @@ export class ProfileUtils { let flatten: IProfileLoaded[] = []; if (!(dependencyResponses == null)) { for (const response of dependencyResponses) { - const moreDependencies = (!(response.dependencyLoadResponses == null)) ? + const moreDependencies = response.dependencyLoadResponses != null ? JSON.parse(JSON.stringify(response.dependencyLoadResponses)) : []; flatten.push(response); delete response.dependencyLoadResponses; diff --git a/packages/imperative/src/profiles/src/utils/V1ProfileRead.ts b/packages/imperative/src/profiles/src/utils/V1ProfileRead.ts new file mode 100644 index 0000000000..6b8bb7da07 --- /dev/null +++ b/packages/imperative/src/profiles/src/utils/V1ProfileRead.ts @@ -0,0 +1,188 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ImperativeError } from "../../../error"; +import { ImperativeConfig } from "../../../utilities"; +import * as fs from "fs"; +import { IProfile } from "../doc/definition/IProfile"; +import { IMetaProfile } from "../doc/definition/IMetaProfile"; +import * as pathPackage from "path"; +import { IProfileTypeConfiguration } from "../doc/config/IProfileTypeConfiguration"; + +const readYaml = require("js-yaml"); + +/** + * The V1ProfileRead class is for reading V1 profiles from disk. + * V1 profiles are not supported as of Zowe V3. Profiles should only be read + * for the purpose of converting the V1 profiles to a current zowe client configuration. + * All "fs" calls are wrapped here and errors are transformed to ImperativeError for + * error handling/flow throughout Imperative. + * + * @export + * @class V1ProfileRead + * @internal + */ +export class V1ProfileRead { + /** + * Read the profile meta file using Yaml "safeLoad" (ensures that no code executes, etc. during the load). The + * meta profile file for a type contains the default profile specification. The meta profile is ALWAYS in YAML + * format (controlled exclusively by the Imperative framework). + * @static + * @param {string} path - The path to the meta profile + * @returns {IMetaProfile} - The meta profile + * @memberof V1ProfileRead + */ + public static readMetaFile(path: string): IMetaProfile { + V1ProfileRead.crashInTeamConfigMode(); + + let meta: IMetaProfile; + try { + meta = readYaml.load(fs.readFileSync(path), "utf8"); + } catch (err) { + throw new ImperativeError({ + msg: `Error reading profile file ("${path}"). Error Details: ${err.message}`, + additionalDetails: err + }, {tag: V1ProfileRead.ERROR_ID}); + } + return meta; + } + + /** + * Accepts the profiles root directory and returns all directories within. The directories within the root + * directory are all assumed to be profile type directories (potentially containing a meta file and profiles + * of that type). + * @static + * @param {string} profileRootDirectory - The profiles root directory to obtain all profiles from. + * @returns {string[]} - The list of profiles returned or a blank array + * @memberof V1ProfileRead + */ + public static getAllProfileDirectories(profileRootDirectory: string): string[] { + V1ProfileRead.crashInTeamConfigMode(); + + let names: string[] = []; + try { + names = fs.readdirSync(profileRootDirectory); + names = names.filter((name) => { + // only return directories, not files + const stats = fs.statSync(pathPackage.join(profileRootDirectory, name)); + return stats.isDirectory(); + }); + } catch (e) { + throw new ImperativeError({ + msg: `An error occurred attempting to read all profile directories from "${profileRootDirectory}". ` + + `Error Details: ${e.message}`, + additionalDetails: e + }, {tag: V1ProfileRead.ERROR_ID}); + } + return names; + } + + /** + * Accepts the profile directory location for a type, reads all filenames, and returns a list of + * profile names that are present within the directory (excluding the meta profile) + * @static + * @param {string} profileTypeDir - The directory for the type + * @param {string} ext - the extension for the profile files (normally YAML) + * @param {string} metaNameForType - the meta name for this type + * @returns {string[]} - A list of all profile names (without path/ext) + * @memberof V1ProfileRead + */ + public static getAllProfileNames(profileTypeDir: string, ext: string, metaNameForType: string): string[] { + V1ProfileRead.crashInTeamConfigMode(); + + const names: string[] = []; + try { + let profileFiles = fs.readdirSync(profileTypeDir); + profileFiles = profileFiles.filter((file) => { + const fullFile = pathPackage.resolve(profileTypeDir, file); + const isYamlFile = fullFile.length > ext.length && fullFile.substring( + fullFile.length - ext.length) === ext; + return isYamlFile && V1ProfileRead.fileToProfileName(fullFile, ext) !== metaNameForType; + }); + for (const file of profileFiles) { + names.push(V1ProfileRead.fileToProfileName(file, ext)); + } + } catch (e) { + throw new ImperativeError({ + msg: `An error occurred attempting to read all profile names from "${profileTypeDir}". ` + + `Error Details: ${e.message}`, + additionalDetails: e + }, {tag: V1ProfileRead.ERROR_ID}); + } + return names; + } + + /** + * Read a profile from disk. Profiles are always assumed to be YAML (YAML "safeLoad" is invoked to perform the load). + * @static + * @param {string} filePath - Path to the profile. + * @param {string} type - The profile type; used to populate the "type" in the profile object (type property not persisted on disk). + * @returns {IProfile} - The profile object. + * @memberof V1ProfileRead + */ + public static readProfileFile(filePath: string, type: string): IProfile { + V1ProfileRead.crashInTeamConfigMode(); + + let profile: IProfile; + try { + profile = readYaml.load(fs.readFileSync(filePath, "utf8")); + } catch (err) { + throw new ImperativeError({ + msg: `Error reading profile file ("${filePath}"). Error Details: ${err.message}`, + additionalDetails: err + }, {tag: V1ProfileRead.ERROR_ID}); + } + return profile; + } + + /** + * Crash if we detect that we are running in team-config mode. + * You should not be able to operate on old-school profiles + * when you are in team-config mode. Give a meaningful + * message as part of our crash. + */ + private static crashInTeamConfigMode() { + if (ImperativeConfig.instance.config?.exists) { + try { + throw new Error( + "Attempted to convert a Zowe V1 profile when a newer Zowe client configuration already exists." + ); + } catch (err) { + throw new ImperativeError({ + msg: err.message, + additionalDetails: err.stack, + }, {tag: V1ProfileRead.ERROR_ID}); + } + } + } + + /** + * Extracts the profile name from the file path/name + * @static + * @param {string} file - the file path to extract the profile name + * @param {string} ext - the extension of the file + * @returns {string} - the profile name + * @memberof V1ProfileRead + */ + private static fileToProfileName(file: string, ext: string): string { + file = pathPackage.basename(file); + return file.substring(0, file.lastIndexOf(ext)); + } + + /** + * Error IO tag for Imperative Errors + * @private + * @static + * @type {string} + * @memberof V1ProfileRead + */ + private static ERROR_ID: string = "V1ProfileRead Read Error"; +} diff --git a/packages/imperative/src/profiles/src/utils/__mocks__/ProfileIO.ts b/packages/imperative/src/profiles/src/utils/__mocks__/V1ProfileRead.ts similarity index 70% rename from packages/imperative/src/profiles/src/utils/__mocks__/ProfileIO.ts rename to packages/imperative/src/profiles/src/utils/__mocks__/V1ProfileRead.ts index 423850240b..bafa1cb5fd 100644 --- a/packages/imperative/src/profiles/src/utils/__mocks__/ProfileIO.ts +++ b/packages/imperative/src/profiles/src/utils/__mocks__/V1ProfileRead.ts @@ -28,203 +28,24 @@ import { ORANGE_PROFILE_TYPE, STRAWBERRY_PROFILE_TYPE, STRAWBERRY_TYPE_SCHEMA -} from "../../../__tests__/TestConstants"; +} from "../../../../cmd/__tests__/profiles/TestConstants"; import { IProfileTypeConfiguration } from "../../doc/config/IProfileTypeConfiguration"; /** - * Mocked profile IO class - for the most part, just reacts differently based on the profile name/path specified + * Mocked V1ProfileRead class - for the most part, just reacts differently based on the profile name/path specified * to simulate certain profile conditions for testing the manager. * * @export - * @class ProfileIO + * @class V1ProfileRead */ -export class ProfileIO { - /** - * Mocked exists checks if the constructed file path contains the profile or meta file name and - * returns the path to the caller. Allows you to indicate what profiles should exist just by the name - * in your tests. - * @static - * @param {string} path - * @returns {string} - * @memberof ProfileIO - */ - public static exists(path: string): string { - if (path.indexOf("green_apple") >= 0) { - return path; - } - if (path.indexOf("red_apple") >= 0) { - return path; - } - if (path.indexOf("green_dependency_apple") >= 0) { - return path; - } - if (path.indexOf("sweet_strawberry") >= 0) { - return path; - } - if (path.indexOf("mackintosh_apple") >= 0) { - return path; - } - if (path.indexOf("mackintosh_error_apple") >= 0) { - return path; - } - if (path.indexOf("sugar_coated_strawberry") >= 0) { - return path; - } - if (path.indexOf("tasty_apples") >= 0) { - return path; - } - if (path.indexOf("chocolate_covered") >= 0) { - return path; - } - if (path.indexOf("old_apple") >= 0) { - return path; - } - if (path.indexOf("banana_with_grape_dep") >= 0) { - return path; - } - if (path.indexOf("grape_with_banana_circular_dep") >= 0) { - return path; - } - if (path.indexOf("apple_with_two_req_dep_circular") >= 0) { - return path; - } - if (path.indexOf("grape_with_apple_circular_dep") >= 0) { - return path; - } - if (path.indexOf("throw_the_apple") >= 0) { - return path; - } - if (path.indexOf("bad_mango") >= 0) { - return path; - } - if (path.indexOf("good_apple") >= 0) { - return path; - } - if (path.indexOf("misshapen_apple") >= 0) { - return path; - } - if (path.indexOf(BLUEBERRY_PROFILE_TYPE + "_meta") >= 0) { - return path; - } - if (path.indexOf("sweet_blueberry") >= 0) { - return path; - } - if (path.indexOf("apples_and_strawberries_and_bananas") >= 0) { - return path; - } - if (path.indexOf("bundle_of_bananas") >= 0) { - return path; - } - if (path.indexOf("chocolate_strawberries") >= 0) { - return path; - } - if (path.indexOf("apples_and_grapes_and_strawberries_and_bananas") >= 0) { - return path; - } - if (path.indexOf("green_grapes") >= 0) { - return path; - } - if (path.indexOf("bananas_and_grapes") >= 0) { - return path; - } - if (path.indexOf("apples_and_grapes_with_error_and_strawberries_and_bananas") >= 0) { - return path; - } - if (path.indexOf("bananas_and_error_grapes") >= 0) { - return path; - } - if (path.indexOf("bad_grapes") >= 0) { - return path; - } - if (path.indexOf("bananas_error_and_grapes") >= 0) { - return path; - } - if (path.indexOf("apples_and_grapes_not_found_and_strawberries_and_bananas") >= 0) { - return path; - } - if (path.indexOf("apple_has_circular") >= 0) { - return path; - } - if (path.indexOf("strawberry_and_apple") >= 0) { - return path; - } - if (path.indexOf("tart_blueberry") >= 0) { - return path; - } - - // The following group is for detecting if configurations already exist - if (path.indexOf(FRUIT_BASKET) >= 0 && path.indexOf(STRAWBERRY_PROFILE_TYPE) >= 0) { - return path; - } - if (path.indexOf(FRUIT_BASKET) >= 0 && path.indexOf(BLUEBERRY_PROFILE_TYPE) >= 0) { - return path; - } - if (path.indexOf(FRUIT_BASKET) >= 0 && path.indexOf(APPLE_PROFILE_TYPE) >= 0) { - return path; - } - if (path.indexOf(FRUIT_BASKET) >= 0 && path.indexOf(GRAPE_PROFILE_TYPE) >= 0) { - return path; - } - - // Used on an optional dependency load - if (path.indexOf("strawberry_no_apple") >= 0) { - return path; - } - - // Used on an optional dependency load - where the dependency is not found - if (path.indexOf("strawberry_not_found_apple") >= 0) { - return path; - } - - return null; - } - - /** - * Usually just succeeds - but throws an error depending on profile name - * @static - * @param {string} name - * @param {string} fullFilePath - * @memberof ProfileIO - */ - public static deleteProfile(name: string, fullFilePath: string) { - if (name.indexOf("mackintosh_error_apple") >= 0) { - throw new Error("IO ERROR DELETING THE APPLE"); - } - } - - /** - * Just here to "succeed" - * @static - * @param {string} path - * @memberof ProfileIO - */ - public static createProfileDirs(path: string) { - // Nothing needs to happen here during the tests - just needs to "succeed" - } - - /** - * Write profile usually succeeds (unless told to throw an error - based on the input profile name) - * @static - * @param {string} fullFilePath - * @param {IProfile} profile - * @memberof ProfileIO - */ - public static writeProfile(fullFilePath: string, profile: IProfile) { - // A profile name of "throw_the_apple", simulates a write failure - // throwing a simple error - just to ensure that there are no unhandled promise rejections, etc - // and that the error is returned to the caller of the "save" API - if (fullFilePath.indexOf("throw_the_apple") >= 0) { - throw new Error("Write file unexpected failure"); - } - } - +export class V1ProfileRead { /** * Mocks the get all profile directores - for the most part, if a certain string is found within the path * input, a certain list will be responded. * @static * @param {string} profileRootDirectory * @returns {string[]} - * @memberof ProfileIO + * @memberof V1ProfileRead */ public static getAllProfileDirectories(profileRootDirectory: string): string[] { if (profileRootDirectory.indexOf(FRUIT_BASKET_BAD) >= 0 || profileRootDirectory.indexOf(FRUIT_BASKET_WORSE) >= 0) { @@ -241,7 +62,7 @@ export class ProfileIO { * @static * @param {string} path * @returns {IMetaProfile} - * @memberof ProfileIO + * @memberof V1ProfileRead */ public static readMetaFile(path: string): IMetaProfile { @@ -335,20 +156,6 @@ export class ProfileIO { return null; } - /** - * Write meta file mocked - only throws and error if the path indicates a particular fruit type - * @static - * @param {IMetaProfile} meta - * @param {string} path - * @memberof ProfileIO - */ - public static writeMetaFile(meta: IMetaProfile, path: string) { - // Mango type causes a throw error from writing the meta file - if (path.indexOf(MANGO_PROFILE_TYPE) >= 0) { - throw new Error("Error writing the meta file"); - } - } - /** * Returns "all" mocked profile names. Used in delete and other tests to check for dependencies, etc. * @static @@ -356,7 +163,7 @@ export class ProfileIO { * @param {string} ext * @param {string} metaNameForType * @returns {string[]} - * @memberof ProfileIO + * @memberof V1ProfileRead */ public static getAllProfileNames(profileTypeDir: string, ext: string, metaNameForType: string): string[] { if (profileTypeDir.indexOf("apple") >= 0) { @@ -376,7 +183,7 @@ export class ProfileIO { * @param {string} filePath * @param {string} type * @returns {IProfile} - * @memberof ProfileIO + * @memberof V1ProfileRead */ public static readProfileFile(filePath: string, type: string): IProfile { @@ -693,6 +500,6 @@ export class ProfileIO { }; } - throw new Error("Profile IO Mock did NOT have a profile for: " + filePath); + throw new Error("V1ProfileRead Mock did NOT have a profile for: " + filePath); } } diff --git a/packages/imperative/src/profiles/src/utils/__tests__/ProfileIO.unit.test.ts b/packages/imperative/src/profiles/src/utils/__tests__/ProfileIO.unit.test.ts deleted file mode 100644 index 4ec7455fcc..0000000000 --- a/packages/imperative/src/profiles/src/utils/__tests__/ProfileIO.unit.test.ts +++ /dev/null @@ -1,604 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import Mock = jest.Mock; - -jest.mock("fs"); -jest.mock("../../../../io/src/IO"); -jest.mock("js-yaml"); -jest.mock("yamljs"); -jest.mock("../../../../utilities/src/ImperativeConfig"); - -import * as fs from "fs"; -import { IO } from "../../../../io/src/IO"; -import { ProfileIO } from "../ProfileIO"; -import { ImperativeError } from "../../../../error/index"; -import { - BANANA_PROFILE_TYPE, - BLUEBERRY_PROFILE_TYPE, - BLUEBERRY_TYPE_SCHEMA, - STRAWBERRY_PROFILE_TYPE -} from "../../../__tests__/TestConstants"; -import { IMetaProfile, IProfile } from "../../../../index"; -import { IProfileTypeConfiguration } from "../../doc/config/IProfileTypeConfiguration"; -import { ImperativeConfig } from "../../../../utilities"; - -const readYaml = require("js-yaml"); -const writeYaml = require("yamljs"); - -const mocks = { - createDirsSync: jest.spyOn(IO, "createDirsSync"), - safeLoad: jest.spyOn(readYaml, "load"), - writeFileSync: jest.spyOn(fs, "writeFileSync"), - yamlStringify: jest.spyOn(writeYaml, "stringify"), - unlinkSync: jest.spyOn(fs, "unlinkSync"), - existsSync: jest.spyOn(fs, "existsSync"), - readdirSync: jest.spyOn(fs, "readdirSync"), - readFileSync: jest.spyOn(fs, "readFileSync"), - statSync: jest.spyOn(fs, "statSync") -}; - -const TEST_DIR_PATH: string = "/__tests__/__results__/data/.testHomeDir"; -const err: string = "IO ERROR!"; - -describe("Profile IO", () => { - beforeEach(() => { - // Mocks need cleared after every test for clean test runs - jest.resetAllMocks(); - }); - - it("should be able to create all profile directories", () => { - mocks.createDirsSync.mockImplementation(((args: any) => { - return; - }) as any); - ProfileIO.createProfileDirs(TEST_DIR_PATH); - expect(mocks.createDirsSync).toHaveBeenCalledWith(TEST_DIR_PATH); - }); - - it("should throw an Imperative Error if an IO error occurs when creating profile directories", () => { - mocks.createDirsSync.mockImplementation((args: any) => { - throw new Error(err); - }); - let error; - try { - ProfileIO.createProfileDirs(TEST_DIR_PATH); - } catch (e) { - error = e; - } - expect(mocks.createDirsSync).toHaveBeenCalledWith(TEST_DIR_PATH); - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain("Profile IO Error: An error occurred creating profile directory:"); - expect(error.message).toContain("Error Details: IO ERROR!"); - }); - - it("should be able to read the meta file", () => { - const meta = { - defaultProfile: [{ - name: "sweet_blueberry", - type: BLUEBERRY_PROFILE_TYPE - }], - configuration: { - type: BLUEBERRY_PROFILE_TYPE, - schema: BLUEBERRY_TYPE_SCHEMA - } - }; - - mocks.safeLoad.mockImplementation((args: any) => { - return meta; - }); - - const readMeta = ProfileIO.readMetaFile(TEST_DIR_PATH); - expect(readMeta).toBeDefined(); - expect(readMeta).toMatchSnapshot(); - }); - - it("should throw an imperative error if an error occurs reading the meta file", () => { - const meta = { - defaultProfile: [{ - name: "sweet_blueberry", - type: BLUEBERRY_PROFILE_TYPE - }], - configuration: { - type: BLUEBERRY_PROFILE_TYPE, - schema: BLUEBERRY_TYPE_SCHEMA - } - }; - - mocks.safeLoad.mockImplementation((args: any) => { - throw new Error(err); - }); - - let error; - try { - const readMeta = ProfileIO.readMetaFile(TEST_DIR_PATH); - } catch (e) { - error = e; - } - - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain("Profile IO Error: Error reading profile file"); - }); - - it("should be able to write a profile", () => { - const prof: IProfile = { - name: "strawberries", - type: "strawberry", - amount: 1000 - }; - mocks.yamlStringify.mockImplementation((args: any) => { - return prof; - }); - let written; - mocks.writeFileSync.mockImplementation(((fullFilePath: string, profile: IProfile) => { - written = profile; - return; - }) as any); - ProfileIO.writeProfile(TEST_DIR_PATH, prof); - expect(written).toBeDefined(); - expect(written).toEqual(prof); - }); - - it("should throw an imperative error if a write profile IO error occurs", () => { - const prof: IProfile = { - name: "strawberries", - type: "strawberry", - amount: 1000 - }; - mocks.yamlStringify.mockImplementation((args: any) => { - return prof; - }); - mocks.writeFileSync.mockImplementation(((fullFilePath: string, profile: IProfile) => { - throw new Error(err); - })as never); - let error; - try { - ProfileIO.writeProfile(TEST_DIR_PATH, prof); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain("Profile IO Error: Error creating profile file"); - expect(error.message).toContain("Error Details: IO ERROR!"); - }); - - it("should allow a delete of a profile", () => { - mocks.unlinkSync.mockImplementation(((args: any): any => { - return; - }) as any); - mocks.existsSync.mockImplementation((args: any): any => { - return undefined; - }); - const profname: string = "bad_apple"; - const fullPath: string = TEST_DIR_PATH + "/" + profname + ".yaml"; - ProfileIO.deleteProfile("bad_apple", fullPath); - expect(mocks.unlinkSync).toBeCalledWith(fullPath); - expect(mocks.existsSync).toBeCalledWith(fullPath); - }); - - it("should throw an imperative error if the file is not deleted", () => { - const profname: string = "bad_apple"; - const fullPath: string = TEST_DIR_PATH + "/" + profname + ".yaml"; - mocks.unlinkSync.mockImplementation(((args: any) => { - return; - }) as any); - mocks.existsSync.mockImplementation(((args: any) => { - return fullPath; - }) as any); - let error; - try { - ProfileIO.deleteProfile("bad_apple", fullPath); - } catch (e) { - error = e; - } - expect(mocks.unlinkSync).toBeCalledWith(fullPath); - expect(mocks.existsSync).toBeCalledWith(fullPath); - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain("Profile IO Error: The profile bad_apple was unable to be deleted. Please check " + - "the path indicated here and try to remove the profile manually:"); - }); - - it("should throw an imperative error if an IO error occurs during a delete", () => { - const profname: string = "bad_apple"; - const fullPath: string = TEST_DIR_PATH + "/" + profname + ".yaml"; - mocks.unlinkSync.mockImplementation((args: any) => { - throw new Error(err); - }); - mocks.existsSync.mockImplementation(((args: any) => { - return fullPath; - }) as any); - let error; - try { - ProfileIO.deleteProfile("bad_apple", fullPath); - } catch (e) { - error = e; - } - expect(mocks.unlinkSync).toBeCalledWith(fullPath); - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain("Profile IO Error: An unexpected profile delete error occurred for profile"); - expect(error.message).toContain("Error Details: IO ERROR!"); - }); - - it("should allow us to check if a profile exists", () => { - mocks.existsSync.mockImplementation((args: any): any => { - return undefined; - }); - const profname: string = "bad_apple"; - const fullPath: string = TEST_DIR_PATH + "/" + profname + ".yaml"; - const path = ProfileIO.exists(fullPath); - expect(path).toBeUndefined(); - expect(mocks.existsSync).toBeCalledWith(fullPath); - }); - - it("should throw an imperative error if an exists IO error occurs", () => { - mocks.existsSync.mockImplementation((args: any) => { - throw new Error(err); - }); - const profname: string = "bad_apple"; - const fullPath: string = TEST_DIR_PATH + "/" + profname + ".yaml"; - let error; - try { - const path = ProfileIO.exists(fullPath); - } catch (e) { - error = e; - } - expect(mocks.existsSync).toBeCalledWith(fullPath); - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain("Profile IO Error: An error occurred checking for the existance of"); - expect(error.message).toContain("Error Details: IO ERROR!"); - }); - - it("should be able to write a meta file", () => { - const meta: IMetaProfile = { - defaultProfile: "sweet_blueberry", - configuration: { - type: BLUEBERRY_PROFILE_TYPE, - schema: BLUEBERRY_TYPE_SCHEMA - } - }; - mocks.yamlStringify.mockImplementation((args: any) => { - return meta; - }); - let written; - mocks.writeFileSync.mockImplementation(((fullFilePath: string, contents: string, args: any) => { - written = contents; - return; - }) as any); - const metaPath = TEST_DIR_PATH + "/" + BLUEBERRY_PROFILE_TYPE + "_meta.yaml"; - const writeMeta = ProfileIO.writeMetaFile(meta, metaPath); - expect(mocks.writeFileSync).toBeCalledWith(metaPath, meta, {encoding: "utf8"}); - expect(written).toBeDefined(); - expect(written).toEqual(meta); - }); - - it("should throw an imperative error if an IO error occurrs during writing the meta file", () => { - const meta: IMetaProfile = { - defaultProfile: "sweet_blueberry", - configuration: { - type: BLUEBERRY_PROFILE_TYPE, - schema: BLUEBERRY_TYPE_SCHEMA - } - }; - mocks.yamlStringify.mockImplementation((args: any) => { - return meta; - }); - mocks.writeFileSync.mockImplementation((fullFilePath: string, contents: string, args: any) => { - throw new Error(err); - }); - const metaPath = TEST_DIR_PATH + "/" + BLUEBERRY_PROFILE_TYPE + "_meta.yaml"; - let error; - try { - ProfileIO.writeMetaFile(meta, metaPath); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(mocks.writeFileSync).toBeCalledWith(metaPath, meta, {encoding: "utf8"}); - expect(error.message).toContain("Profile IO Error: An error occurred converting and writing the meta profile to"); - expect(error.message).toContain("Error Details: IO ERROR!"); - }); - - it("should be able to return the profile name from a file name", () => { - const path = TEST_DIR_PATH + "/" + BLUEBERRY_PROFILE_TYPE + ".yaml"; - const name: string = ProfileIO.fileToProfileName(path as any, ".yaml"); - expect(name).toBe(BLUEBERRY_PROFILE_TYPE); - }); - - it("should return a list of profile types", () => { - const types: string[] = [BLUEBERRY_PROFILE_TYPE, STRAWBERRY_PROFILE_TYPE, BANANA_PROFILE_TYPE]; - mocks.readdirSync.mockImplementationOnce(((path: any) => { - return types; - }) as any); - mocks.statSync.mockImplementation(((filePath: string) => { - return { - isDirectory: jest.fn(() => { - return true; - }), - }; - }) as any); - const returnedTypes: string[] = ProfileIO.getAllProfileDirectories(TEST_DIR_PATH); - expect(mocks.readdirSync).toBeCalledWith(TEST_DIR_PATH); - expect(returnedTypes).toEqual(types); - }); - - it("should return a list of profile types but filter out non directory entries", () => { - const types: string[] = [BLUEBERRY_PROFILE_TYPE, STRAWBERRY_PROFILE_TYPE, BANANA_PROFILE_TYPE]; - mocks.readdirSync.mockImplementationOnce(((path: any) => { - return types; - }) as any); - mocks.statSync.mockImplementation(((filePath: string) => { - return { - isDirectory: jest.fn(() => { - // pretend "banana" is not a directory - return !filePath.includes(BANANA_PROFILE_TYPE); - }), - }; - }) as any); - const returnedTypes: string[] = ProfileIO.getAllProfileDirectories(TEST_DIR_PATH); - expect(mocks.readdirSync).toBeCalledWith(TEST_DIR_PATH); - expect(returnedTypes).toEqual(types.filter((type) => { - // results shouldn't contain banana - return type !== BANANA_PROFILE_TYPE; - })); - }); - - it("should throw an imperative error if the read directory IO error occurs", () => { - const types: string[] = [BLUEBERRY_PROFILE_TYPE, STRAWBERRY_PROFILE_TYPE, BANANA_PROFILE_TYPE]; - mocks.readdirSync.mockImplementation((path: any) => { - throw new Error(err); - }); - let error; - try { - const returnedTypes: string[] = ProfileIO.getAllProfileDirectories(TEST_DIR_PATH); - } catch (e) { - error = e; - } - expect(mocks.readdirSync).toBeCalledWith(TEST_DIR_PATH); - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain("An error occurred attempting to read all profile directories from"); - expect(error.message).toContain("Error Details: IO ERROR!"); - }); - - it("should return a list of profile names", () => { - const fileNames: string[] = ["rotten.yaml", "fresh.yaml", "apple_meta.yaml"]; - const names: string[] = ["rotten", "fresh"]; - mocks.readdirSync.mockImplementation(((path: any) => { - return fileNames; - }) as any); - const returnedTypes: string[] = ProfileIO.getAllProfileNames(TEST_DIR_PATH, ".yaml", "apple_meta"); - expect(mocks.readdirSync).toBeCalledWith(TEST_DIR_PATH); - expect(returnedTypes).toEqual(names); - }); - - it("should throw an imperative error if an IO error occurs getting profile names", () => { - const fileNames: string[] = ["rotten.yaml", "fresh.yaml", "apple_meta.yaml"]; - const names: string[] = ["rotten", "fresh"]; - mocks.readdirSync.mockImplementation((path: any) => { - throw new Error(err); - }); - let error; - try { - const returnedTypes: string[] = ProfileIO.getAllProfileNames(TEST_DIR_PATH, ".yaml", "apple_meta"); - } catch (e) { - error = e; - } - expect(mocks.readdirSync).toBeCalledWith(TEST_DIR_PATH); - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain("An error occurred attempting to read all profile names from"); - expect(error.message).toContain("Error Details: IO ERROR!"); - }); - - it("should be able to read a profile", () => { - const prof: IProfile = { - name: "strawberries", - type: "strawberry", - amount: 1000 - }; - mocks.safeLoad.mockImplementation((args: any) => { - return prof; - }); - const profile = ProfileIO.readProfileFile(TEST_DIR_PATH, "strawberry"); - expect(profile).toBeDefined(); - expect(profile).toEqual(prof); - }); - - it("should throw an imperative error if a profile IO read error occurs", () => { - const prof: IProfile = { - name: "strawberries", - type: "strawberry", - amount: 1000 - }; - mocks.safeLoad.mockImplementation((args: any) => { - throw new Error(err); - }); - let error; - try { - const profile = ProfileIO.readProfileFile(TEST_DIR_PATH, "strawberry"); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain("Error reading profile file"); - expect(error.message).toContain("Error Details: IO ERROR!"); - }); - describe("Profile operations should crash in team-config mode", () => { - const configModeErr = "Profile IO Error: A Zowe V1 profile operation was attempted with a Zowe V2 configuration in use."; - - beforeEach(() => { - /* Pretend that we have a team config. - * config is a getter of a property, so mock we the property. - */ - Object.defineProperty(ImperativeConfig.instance, "config", { - configurable: true, - get: jest.fn(() => { - return { - exists: true - }; - }) - }); - }); - - afterEach(() => { - // set us back to old-school profile mode - Object.defineProperty(ImperativeConfig.instance, "config", { - configurable: true, - get: jest.fn(() => { - return { - exists: false - }; - }) - }); - }); - - it("should crash in createProfileDirs", () => { - let error; - try { - ProfileIO.createProfileDirs(TEST_DIR_PATH); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain(configModeErr); - }); - - it("should crash in readMetaFile", () => { - let error; - try { - ProfileIO.readMetaFile(TEST_DIR_PATH); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain(configModeErr); - }); - - it("should crash in writeProfile", () => { - const prof: IProfile = { - name: "strawberries", - type: "strawberry", - amount: 1000 - }; - - let error; - try { - ProfileIO.writeProfile(TEST_DIR_PATH, prof); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain(configModeErr); - }); - - it("should crash in deleteProfile", () => { - let error; - try { - ProfileIO.deleteProfile("SomeName", TEST_DIR_PATH); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain(configModeErr); - }); - - it("should crash in exists", () => { - let error; - try { - ProfileIO.exists(TEST_DIR_PATH); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain(configModeErr); - }); - - it("should crash in writeMetaFile", () => { - const meta: IMetaProfile = { - defaultProfile: "sweet_blueberry", - configuration: { - type: BLUEBERRY_PROFILE_TYPE, - schema: BLUEBERRY_TYPE_SCHEMA - } - }; - - let error; - try { - ProfileIO.writeMetaFile(meta, TEST_DIR_PATH); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain(configModeErr); - }); - - it("should crash in fileToProfileName", () => { - let error; - try { - ProfileIO.fileToProfileName(TEST_DIR_PATH, ".yaml"); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain(configModeErr); - }); - - it("should crash in getAllProfileDirectories", () => { - let error; - try { - ProfileIO.getAllProfileDirectories(TEST_DIR_PATH); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain(configModeErr); - }); - - it("should crash in getAllProfileNames", () => { - let error; - try { - ProfileIO.getAllProfileNames(TEST_DIR_PATH, ".yaml", "apple_meta"); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain(configModeErr); - }); - - it("should crash in readProfileFile", () => { - let error; - try { - ProfileIO.readProfileFile(TEST_DIR_PATH, "strawberry"); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toContain(configModeErr); - }); - }); -}); diff --git a/packages/imperative/src/profiles/src/utils/__tests__/ProfileUtils.unit.test.ts b/packages/imperative/src/profiles/src/utils/__tests__/ProfileUtils.unit.test.ts index c645aeb82d..3b778b7e64 100644 --- a/packages/imperative/src/profiles/src/utils/__tests__/ProfileUtils.unit.test.ts +++ b/packages/imperative/src/profiles/src/utils/__tests__/ProfileUtils.unit.test.ts @@ -14,7 +14,9 @@ jest.mock("path"); import { ProfileUtils } from "../ProfileUtils"; import * as path from "path"; import { IProfileLoaded } from "../../../../index"; -import { APPLE_TWO_REQ_DEP_BANANA_ONE_REQ_DEP_GRAPE_ONE_REQ_DEP, BLUEBERRY_PROFILE_TYPE } from "../../../__tests__/TestConstants"; +import { + APPLE_TWO_REQ_DEP_BANANA_ONE_REQ_DEP_GRAPE_ONE_REQ_DEP, BLUEBERRY_PROFILE_TYPE +} from "./TestConstants"; const mocks = { normalize: path.normalize as unknown as Mock diff --git a/packages/imperative/src/profiles/__tests__/TestConstants.ts b/packages/imperative/src/profiles/src/utils/__tests__/TestConstants.ts similarity index 99% rename from packages/imperative/src/profiles/__tests__/TestConstants.ts rename to packages/imperative/src/profiles/src/utils/__tests__/TestConstants.ts index 9ad82d05c9..06a6eb8c18 100644 --- a/packages/imperative/src/profiles/__tests__/TestConstants.ts +++ b/packages/imperative/src/profiles/src/utils/__tests__/TestConstants.ts @@ -9,7 +9,7 @@ * */ -import { IProfileTypeConfiguration } from "../src/doc/config/IProfileTypeConfiguration"; +import { IProfileTypeConfiguration } from "../../../src/doc/config/IProfileTypeConfiguration"; export const TEST_PROFILE_ROOT_DIR: string = "__tests__/__results__/test_profiles/root/dir/"; diff --git a/packages/imperative/src/profiles/src/utils/__tests__/V1ProfileRead.unit.test.ts b/packages/imperative/src/profiles/src/utils/__tests__/V1ProfileRead.unit.test.ts new file mode 100644 index 0000000000..7596d3cafe --- /dev/null +++ b/packages/imperative/src/profiles/src/utils/__tests__/V1ProfileRead.unit.test.ts @@ -0,0 +1,281 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +jest.mock("fs"); +jest.mock("../../../../io/src/IO"); +jest.mock("js-yaml"); +jest.mock("../../../../utilities/src/ImperativeConfig"); + +import * as fs from "fs"; +import { IO } from "../../../../io/src/IO"; +import { V1ProfileRead } from "../V1ProfileRead"; +import { ImperativeError } from "../../../../error/index"; +import { + BANANA_PROFILE_TYPE, + BLUEBERRY_PROFILE_TYPE, + BLUEBERRY_TYPE_SCHEMA, + STRAWBERRY_PROFILE_TYPE +} from "./TestConstants"; +import { IProfile } from "../../../../index"; +import { ImperativeConfig } from "../../../../utilities"; + +const readYaml = require("js-yaml"); + +const mocks = { + createDirsSync: jest.spyOn(IO, "createDirsSync"), + safeLoad: jest.spyOn(readYaml, "load"), + writeFileSync: jest.spyOn(fs, "writeFileSync"), + unlinkSync: jest.spyOn(fs, "unlinkSync"), + existsSync: jest.spyOn(fs, "existsSync"), + readdirSync: jest.spyOn(fs, "readdirSync"), + readFileSync: jest.spyOn(fs, "readFileSync"), + statSync: jest.spyOn(fs, "statSync") +}; + +const TEST_DIR_PATH: string = "/__tests__/__results__/data/.testHomeDir"; +const err: string = "IO ERROR!"; + +describe("V1 Profile Conversion", () => { + beforeEach(() => { + // Mocks need cleared after every test for clean test runs + jest.resetAllMocks(); + }); + + it("should be able to read the meta file", () => { + const meta = { + defaultProfile: [{ + name: "sweet_blueberry", + type: BLUEBERRY_PROFILE_TYPE + }], + configuration: { + type: BLUEBERRY_PROFILE_TYPE, + schema: BLUEBERRY_TYPE_SCHEMA + } + }; + + mocks.safeLoad.mockImplementation((args: any) => { + return meta; + }); + + const readMeta = V1ProfileRead.readMetaFile(TEST_DIR_PATH); + expect(readMeta).toBeDefined(); + expect(readMeta).toMatchSnapshot(); + }); + + it("should throw an imperative error if an error occurs reading the meta file", () => { + mocks.safeLoad.mockImplementation((args: any) => { + throw new Error(err); + }); + + let error; + try { + V1ProfileRead.readMetaFile(TEST_DIR_PATH); + } catch (e) { + error = e; + } + + expect(error).toBeDefined(); + expect(error instanceof ImperativeError).toBe(true); + expect(error.message).toContain("V1ProfileRead Read Error: Error reading profile file"); + }); + + it("should return a list of profile types", () => { + const types: string[] = [BLUEBERRY_PROFILE_TYPE, STRAWBERRY_PROFILE_TYPE, BANANA_PROFILE_TYPE]; + mocks.readdirSync.mockImplementationOnce(((path: any) => { + return types; + }) as any); + mocks.statSync.mockImplementation(((filePath: string) => { + return { + isDirectory: jest.fn(() => { + return true; + }), + }; + }) as any); + const returnedTypes: string[] = V1ProfileRead.getAllProfileDirectories(TEST_DIR_PATH); + expect(mocks.readdirSync).toHaveBeenCalledWith(TEST_DIR_PATH); + expect(returnedTypes).toEqual(types); + }); + + it("should return a list of profile types but filter out non directory entries", () => { + const types: string[] = [BLUEBERRY_PROFILE_TYPE, STRAWBERRY_PROFILE_TYPE, BANANA_PROFILE_TYPE]; + mocks.readdirSync.mockImplementationOnce(((path: any) => { + return types; + }) as any); + mocks.statSync.mockImplementation(((filePath: string) => { + return { + isDirectory: jest.fn(() => { + // pretend "banana" is not a directory + return !filePath.includes(BANANA_PROFILE_TYPE); + }), + }; + }) as any); + const returnedTypes: string[] = V1ProfileRead.getAllProfileDirectories(TEST_DIR_PATH); + expect(mocks.readdirSync).toHaveBeenCalledWith(TEST_DIR_PATH); + expect(returnedTypes).toEqual(types.filter((type) => { + // results shouldn't contain banana + return type !== BANANA_PROFILE_TYPE; + })); + }); + + it("should throw an imperative error if the read directory IO error occurs", () => { + mocks.readdirSync.mockImplementation((path: any) => { + throw new Error(err); + }); + let error; + try { + V1ProfileRead.getAllProfileDirectories(TEST_DIR_PATH); + } catch (e) { + error = e; + } + expect(mocks.readdirSync).toHaveBeenCalledWith(TEST_DIR_PATH); + expect(error).toBeDefined(); + expect(error instanceof ImperativeError).toBe(true); + expect(error.message).toContain("An error occurred attempting to read all profile directories from"); + expect(error.message).toContain("Error Details: IO ERROR!"); + }); + + it("should return a list of profile names", () => { + const fileNames: string[] = ["rotten.yaml", "fresh.yaml", "apple_meta.yaml"]; + const names: string[] = ["rotten", "fresh"]; + mocks.readdirSync.mockImplementation(((path: any) => { + return fileNames; + }) as any); + const returnedTypes: string[] = V1ProfileRead.getAllProfileNames(TEST_DIR_PATH, ".yaml", "apple_meta"); + expect(mocks.readdirSync).toHaveBeenCalledWith(TEST_DIR_PATH); + expect(returnedTypes).toEqual(names); + }); + + it("should throw an imperative error if an IO error occurs getting profile names", () => { + mocks.readdirSync.mockImplementation((path: any) => { + throw new Error(err); + }); + let error; + try { + V1ProfileRead.getAllProfileNames(TEST_DIR_PATH, ".yaml", "apple_meta"); + } catch (e) { + error = e; + } + expect(mocks.readdirSync).toHaveBeenCalledWith(TEST_DIR_PATH); + expect(error).toBeDefined(); + expect(error instanceof ImperativeError).toBe(true); + expect(error.message).toContain("An error occurred attempting to read all profile names from"); + expect(error.message).toContain("Error Details: IO ERROR!"); + }); + + it("should be able to read a profile", () => { + const prof: IProfile = { + name: "strawberries", + type: "strawberry", + amount: 1000 + }; + mocks.safeLoad.mockImplementation((args: any) => { + return prof; + }); + const profile = V1ProfileRead.readProfileFile(TEST_DIR_PATH, "strawberry"); + expect(profile).toBeDefined(); + expect(profile).toEqual(prof); + }); + + it("should throw an imperative error if a V1 Profile Conversion read error occurs", () => { + mocks.safeLoad.mockImplementation((args: any) => { + throw new Error(err); + }); + let error; + try { + V1ProfileRead.readProfileFile(TEST_DIR_PATH, "strawberry"); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error instanceof ImperativeError).toBe(true); + expect(error.message).toContain("Error reading profile file"); + expect(error.message).toContain("Error Details: IO ERROR!"); + }); + + describe("Profile operations should crash in team-config mode", () => { + const configModeErr = "V1ProfileRead Read Error: " + + "Attempted to convert a Zowe V1 profile when a newer Zowe client configuration already exists."; + + beforeEach(() => { + /* Pretend that we have a team config. + * config is a getter of a property, so mock we the property. + */ + Object.defineProperty(ImperativeConfig.instance, "config", { + configurable: true, + get: jest.fn(() => { + return { + exists: true + }; + }) + }); + }); + + afterEach(() => { + // set us back to old-school profile mode + Object.defineProperty(ImperativeConfig.instance, "config", { + configurable: true, + get: jest.fn(() => { + return { + exists: false + }; + }) + }); + }); + + it("should crash in readMetaFile", () => { + let error; + try { + V1ProfileRead.readMetaFile(TEST_DIR_PATH); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error instanceof ImperativeError).toBe(true); + expect(error.message).toContain(configModeErr); + }); + + it("should crash in getAllProfileDirectories", () => { + let error; + try { + V1ProfileRead.getAllProfileDirectories(TEST_DIR_PATH); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error instanceof ImperativeError).toBe(true); + expect(error.message).toContain(configModeErr); + }); + + it("should crash in getAllProfileNames", () => { + let error; + try { + V1ProfileRead.getAllProfileNames(TEST_DIR_PATH, ".yaml", "apple_meta"); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error instanceof ImperativeError).toBe(true); + expect(error.message).toContain(configModeErr); + }); + + it("should crash in readProfileFile", () => { + let error; + try { + V1ProfileRead.readProfileFile(TEST_DIR_PATH, "strawberry"); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error instanceof ImperativeError).toBe(true); + expect(error.message).toContain(configModeErr); + }); + }); +}); diff --git a/packages/imperative/src/profiles/src/utils/__tests__/__snapshots__/ProfileIO.unit.test.ts.snap b/packages/imperative/src/profiles/src/utils/__tests__/__snapshots__/V1ProfileRead.unit.test.ts.snap similarity index 87% rename from packages/imperative/src/profiles/src/utils/__tests__/__snapshots__/ProfileIO.unit.test.ts.snap rename to packages/imperative/src/profiles/src/utils/__tests__/__snapshots__/V1ProfileRead.unit.test.ts.snap index a8db4524e1..7b3284aff2 100644 --- a/packages/imperative/src/profiles/src/utils/__tests__/__snapshots__/ProfileIO.unit.test.ts.snap +++ b/packages/imperative/src/profiles/src/utils/__tests__/__snapshots__/V1ProfileRead.unit.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Profile IO should be able to read the meta file 1`] = ` +exports[`V1 Profile Conversion should be able to read the meta file 1`] = ` Object { "configuration": Object { "schema": Object { diff --git a/packages/imperative/src/profiles/src/validation/__tests__/ProfileValidation.unit.test.ts b/packages/imperative/src/profiles/src/validation/__tests__/ProfileValidation.unit.test.ts deleted file mode 100644 index 04691e2eef..0000000000 --- a/packages/imperative/src/profiles/src/validation/__tests__/ProfileValidation.unit.test.ts +++ /dev/null @@ -1,427 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { inspect } from "util"; -import { TestLogger } from "../../../../../__tests__/src/TestLogger"; -import { IProfile } from "../../doc/definition/IProfile"; -import { IProfileValidationPlan } from "../doc/IProfileValidationPlan"; -import { IProfileValidationReport } from "../doc/IProfileValidationReport"; -import { IProfileValidationTaskResult } from "../doc/IProfileValidationTaskResult"; -import { ProfileValidator } from "../api/ProfileValidator"; -import { IProfileValidationTask } from "../../.."; - -jest.mock("../../../../imperative/src/Imperative"); - - -const oldForceColorOption = process.env.FORCE_COLOR; - -describe("We should provide the ability to validate Imperative CLI profiles by trying out different APIs", () => { - beforeAll(async () => { - process.env.FORCE_COLOR = "0"; - }); - const displayName = "dummy"; - afterAll(() => { - process.env.FORCE_COLOR = oldForceColorOption; - } - ); - const dummyProfile: IProfile = {name: "dummy", type: "dummy"}; - - it("If we have a mock plan with a failing parent test, the validation should fail and " + - "none of the tasks dependent on the failing task should run ", () => { - let anyTaskRun = false; - const plan: IProfileValidationPlan = { - tasks: [{ - name: "Master task", - description: "This will fail, and none of the rest should run ", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - done({ - outcome: "Failed", - resultDescription: "Failing master task" - }); - }, - dependentTasks: [ - { - name: "Task one", - description: "First task which should not run", - taskFunction: async (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - anyTaskRun = true; // shouldn't happen! - done({ - outcome: "Warning", - resultDescription: "This should not run!" - }); - }, - dependentTasks: [ - { - name: "Task two", - description: "Two level nested task", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - anyTaskRun = true; // shouldn't happen! - done({ - outcome: "Warning", - resultDescription: "This should not run!" - }); - } - }] - }, { - name: "Task three", - description: "Second task which should not run", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - anyTaskRun = true; // shouldn't happen! - done({ - outcome: "Warning", - resultDescription: "This should not run!" - }); - } - } - ] - }] - }; - - return ProfileValidator.validate(dummyProfile, plan, displayName).then((report: IProfileValidationReport) => { - const textReport = ProfileValidator.getTextDisplayForReport(report, plan, displayName, "yellow", - "dummy", "dummy"); - TestLogger.info(textReport); - expect(report.overallResult).toEqual("Failed"); - expect(anyTaskRun).toBeFalsy(); - - }); - }); - - it("If we have a mock plan with a parent test that gets a warning, the validation should fail and " + - "none of the tasks dependent on the failing task should run ", () => { - let anyTaskRun = false; - const plan: IProfileValidationPlan = { - tasks: [{ - name: "Master task", - description: "This will fail, and none of the rest should run ", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - done({ - outcome: "Warning", - resultDescription: "Failing master task" - }); - }, - dependentTasks: [ - { - name: "Task one", - description: "First task which should not run", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - anyTaskRun = true; // shouldn't happen! - done({ - outcome: "Warning", - resultDescription: "This should not run!" - }); - }, - dependentTasks: [ - { - name: "Task two", - description: "Two level nested task", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - anyTaskRun = true; // shouldn't happen! - done({ - outcome: "Warning", - resultDescription: "This should not run!" - }); - } - }] - }, { - name: "Task three", - description: "Second task which should not run", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - anyTaskRun = true; // shouldn't happen! - done({ - outcome: "Warning", - resultDescription: "This should not run!" - }); - } - } - ] - }] - }; - - return ProfileValidator.validate(dummyProfile, plan, displayName) - .then((report: IProfileValidationReport) => { - const textReport = ProfileValidator.getTextDisplayForReport(report, plan, displayName, "yellow", - "dummy", "dummy"); - expect(report.overallResult).toEqual("Warning"); - expect(anyTaskRun).toBeFalsy(); - expect(textReport).toContain("ambiguous results"); - }); - }); - - it("If we have a mock plan with a passing parent test, one failing task and two passing tasks, " + - "the overall result should be failure ", () => { - - const plan: IProfileValidationPlan = { - - tasks: [{ - name: "Master task", - description: "This will fail, and none of the rest should run ", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - done({ - outcome: "OK", - resultDescription: "This should pass" - }); - }, - dependentTasks: [ - { - name: "Task one", - description: "First task which succeeds", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - done({ - outcome: "OK", - resultDescription: "Passes" - }); - }, - }, - { - name: "Task two", - description: "Second task which fails", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - done({ - outcome: "Failed", - resultDescription: "Fails" - }); - }, - - }, { - name: "Task three", - description: "Third task which succeeds", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - done({ - outcome: "OK", - resultDescription: "Passes" - }); - } - } - ] - }] - }; - - return ProfileValidator.validate(dummyProfile, plan, displayName).then((report: IProfileValidationReport) => { - const textReport = ProfileValidator.getTextDisplayForReport(report, plan, displayName, "yellow", - "dummy", "dummy"); - expect(report.overallResult).toEqual("Failed"); - expect(textReport).toContain("will not function"); - }); - }); - - const goodPlan: IProfileValidationPlan = { - tasks: [{ - name: "Master task", - description: "This will succeed, the rest should run", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - done({ - outcome: "OK", - resultDescription: "This should pass" - }); - }, - dependentTasks: [ - { - name: "Task one", - description: "First task which succeeds", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - done({ - outcome: "OK", - resultDescription: "This should pass" - }); - } - }, - { - name: "Task two", - description: "Second task which fails", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - done({ - outcome: "OK", - resultDescription: "This should pass" - }); - }, - - }, { - name: "Task three", - description: "Third task which succeeds", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - done({ - outcome: "OK", - resultDescription: "This should pass" - }); - } - } - ] - }] - }; - it("If we have a mock plan with all passing tests, the result should be a successful validation", () => { - - - return ProfileValidator.validate(dummyProfile, goodPlan, displayName).then((report: IProfileValidationReport) => { - const textReport = ProfileValidator.getTextDisplayForReport(report, goodPlan, displayName, "yellow", - "dummy", "dummy"); - TestLogger.info(textReport); - expect(report.overallResult).toEqual("OK"); - expect(textReport).toContain("valid and ready"); - }); - }); - - it("If we have a mock plan with a parent test that throws an unexpected exception, " + - "the dependent tasks should still be skipped and we should still get " + - "a report ", () => { - let anyTaskRun = false; - const errorMessage = "This shouldn't disrupt the flow"; - const plan: IProfileValidationPlan = { - tasks: [{ - name: "Master task", - description: "This will fail, and none of the rest should run ", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - throw new Error(errorMessage); - }, - dependentTasks: [ - { - name: "Task one", - description: "First task which should not run", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - anyTaskRun = true; // shouldn't happen! - done({ - outcome: "Warning", - resultDescription: "This should not run!" - }); - }, - dependentTasks: [ - { - name: "Task two", - description: "Two level nested task", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - anyTaskRun = true; // shouldn't happen! - done({ - outcome: "Warning", - resultDescription: "This should not run!" - }); - } - }] - }, { - name: "Task three", - description: "Second task which should not run", - taskFunction: (profile: any, done: (result: IProfileValidationTaskResult) => void) => { - anyTaskRun = true; // shouldn't happen! - done({ - outcome: "Warning", - resultDescription: "This should not run!" - }); - } - } - ] - }] - }; - - return ProfileValidator.validate(dummyProfile, plan, displayName).then((report: IProfileValidationReport) => { - const textReport = ProfileValidator.getTextDisplayForReport(report, plan, displayName, "yellow", - "dummy", "dummy"); - TestLogger.info(textReport); - expect(report.taskResults[0].resultDescription).toContain(errorMessage); - expect(report.overallResult).toEqual("Failed"); - expect(anyTaskRun).toBeFalsy(); - }); - }); - - it("If we get a text report for a validation plan, the report should contain all of the descriptions " + - "for each task", () => { - let expectedWords: string[] = []; - const findExpectedWordsInTask = (task: IProfileValidationTask) => { - expectedWords = expectedWords.concat(task.description.split(" ")); - for (const dependent of (task.dependentTasks || [])) { - findExpectedWordsInTask(dependent); - } - }; - for (const task of goodPlan.tasks) { - findExpectedWordsInTask(task); - } - const textPlanReport = ProfileValidator.getTextDisplayForPlan(goodPlan, dummyProfile, "yellow"); - for (const word of expectedWords) { - expect(textPlanReport).toContain(word); - } - }); - - it("If we try to validate with a plan with no tasks in it, an error should be thrown to let " + - "profile/module contributors know that their plan is invalid ", async () => { - const plan: IProfileValidationPlan = {tasks: []}; - let caughtError; - try { - await ProfileValidator.validate(dummyProfile, plan, displayName); - } catch (error) { - caughtError = error; - TestLogger.info("Got an error during validation as expected: " + inspect(error)); - } - expect(caughtError).toBeDefined(); - expect(caughtError.message).toContain("tasks"); - }); - - it("If we validate a profile with a result description that is too long, it should be truncated", async () => { - const thirtyTimes = 30; - const longDescription = Array(thirtyTimes) - .join("ABCDEFGHIJKLMNOPQRSTUVABCDEFGHIJKLMNOPQRSTUVABCDEFGHIJKLMNOPQRSTUV"); - const plan: IProfileValidationPlan = { - tasks: [{ - name: "Task one", - description: "Task which has a long result description", - taskFunction: (profile: any, taskDone: (result: IProfileValidationTaskResult) => void) => { - taskDone({ - outcome: "Warning", - resultDescription: longDescription - }); - } - }] - }; - let textReport: string; - let caughtError; - try { - const report = await ProfileValidator.validate(dummyProfile, plan, displayName); - textReport = ProfileValidator.getTextDisplayForReport(report, plan, displayName, "yellow", "dummy", "dummy"); - } catch (error) { - caughtError = error; - TestLogger.info("Got an error during unexpected validation: " + inspect(error)); - } - expect(caughtError).toBeUndefined(); - expect(textReport).toContain(longDescription.substring(0, 10)); // expect the report to have - // at least ten characters in a row of the description (Could test more but it's in a tabular format - // so the characters don't appear together - expect(textReport).toContain("..."); // expect it to be truncated - }); - - it("a failed profile validation report should include specified failure suggestions", async () => { - const failureSuggestion = "Try fixing whatever is wrong"; - const plan: IProfileValidationPlan = { - tasks: [{ - name: "Task one", - description: "Task which has a long result description", - taskFunction: (profile: any, taskDone: (result: IProfileValidationTaskResult) => void) => { - taskDone({ - outcome: "Failed", - resultDescription: "The task failed" - }); - } - }], - failureSuggestions: failureSuggestion - }; - let textReport: string; - let caughtError; - try { - const report = await ProfileValidator.validate(dummyProfile, plan, displayName); - textReport = ProfileValidator.getTextDisplayForReport(report, plan, displayName, "yellow", "dummy", "dummy"); - } catch (error) { - caughtError = error; - TestLogger.info("Got an error during unexpected validation: " + inspect(error)); - } - expect(caughtError).toBeUndefined(); - // each word of the failure suggestions should appear (tabular format - // so the characters don't appear together) - for (const word of failureSuggestion.split(" ")) { - expect(textReport).toContain(word); - } - }); -}); diff --git a/packages/imperative/src/profiles/src/validation/api/ProfileValidator.ts b/packages/imperative/src/profiles/src/validation/api/ProfileValidator.ts deleted file mode 100644 index 36de8399df..0000000000 --- a/packages/imperative/src/profiles/src/validation/api/ProfileValidator.ts +++ /dev/null @@ -1,412 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IProfileValidationReport } from "../doc/IProfileValidationReport"; -import { IProfileValidationPlan } from "../doc/IProfileValidationPlan"; -import { - IProfileValidationTask, - IProfileValidationTaskFunction, - VALIDATION_OUTCOME -} from "../doc/IProfileValidationTask"; -import { IProfileValidationTaskResult } from "../doc/IProfileValidationTaskResult"; -import { Logger, LoggerUtils } from "../../../../logger"; -import { TextUtils } from "../../../../utilities"; -import { IPromiseWithProgress, ITaskWithStatus, TaskProgress, TaskStage } from "../../../../operations"; -import { ICommandOptionDefinition } from "../../../../cmd"; -import { IProfile } from "../../doc/definition/IProfile"; -import { CliUtils } from "../../../../utilities/src/CliUtils"; - -/** - * API for going through the full validation test for a Brightside CLI profile - * and producing validation report - */ -export class ProfileValidator { - - /** - * The key used to access the filename for the type containing the profile - * validation plan object. On your profile validation command definition, - * specify the filename in .customize[CUSTOMIZE_PLAN_KEY] - * @type {string} - */ - public static readonly CUSTOMIZE_PLAN_KEY = "validationPlanModule"; - - /** - * The command line option for printing the validation plan only - */ - public static get PRINT_PLAN_OPTION(): ICommandOptionDefinition { - return { - name: "print-plan-only", aliases: ["plan", "p"], - description: "Instead of validating your profile, print out " + - "a table of the tasks used for validation. This will explain the different services and " + - "functionality that will be tested during profile validation.", - type: "boolean" - }; - } - - /** - * Produce a profile validation report for a specific profile - * @param {IProfile} profile the profile to validate - * @param {IProfileValidationPlan} plan - the profile validation testing plan - * @param productDisplayName - the display name for your CLI - * @returns {IPromiseWithProgress} a promise of the validation report, with an additional field - * that can be used to create a progress bar or track progress in another UI - */ - public static validate(profile: IProfile, - plan: IProfileValidationPlan, - productDisplayName: string): IPromiseWithProgress { - const log = Logger.getImperativeLogger(); - const progress: ITaskWithStatus = { - stageName: TaskStage.IN_PROGRESS, - percentComplete: TaskProgress.ZERO_PERCENT, - statusMessage: "Preparing to validate profile" - }; - const promise: any = new Promise((validationComplete) => { - const report: IProfileValidationReport = { - overallResult: "OK", // start with success and change it if there are any failures - taskResults: [], - overallMessage: "Your profile is valid and ready for use with " + - productDisplayName, - profile - }; - log.debug("Validating profile with %d tasks", plan.tasks.length); - - let tasksCompleted = 0; - let numTasksToComplete = 0; - const countTasks = (task: IProfileValidationTask) => { - numTasksToComplete++; - if (!(task.dependentTasks == null)) { - for (const dependent of task.dependentTasks) { - countTasks(dependent); - } - } - }; - for (const task of plan.tasks) { - countTasks(task); // get the total number of tasks - } - if (numTasksToComplete === 0) { - throw new Error("Validation plan has no tasks! If you want to validate a profile, " + - "you need at least one task in your plan."); - } - - let tasksToRun = [].concat(plan.tasks); - - // define how tasks will be handled when we run them - const runTask = () => { - const currentTask = tasksToRun[0]; - tasksToRun = tasksToRun.slice(1); // take off the task we're working on now - - const skipDependentTask = (dependentTask: IProfileValidationTask, result: IProfileValidationTaskResult) => { - // add a 'skipped task' result for each descendant dependent task - const skippedResult: IProfileValidationTaskResult = { - taskName: dependentTask.name, - associatedEndpoints: dependentTask.associatedEndpoints, - outcome: "Warning", - resultDescription: TextUtils.formatMessage( - "Skipped due to '%s' getting a result of %s", - currentTask.name, this.outcomeToString(result.outcome)) - }; - report.taskResults.push(skippedResult); - tasksCompleted++; - if (!(dependentTask.dependentTasks == null)) { - for (const grandDependent of dependentTask.dependentTasks) { - skipDependentTask(grandDependent, result); - } - } - }; - - const taskFunction: IProfileValidationTaskFunction = currentTask.taskFunction; - progress.percentComplete = (((tasksCompleted) / numTasksToComplete) * TaskProgress.ONE_HUNDRED_PERCENT); - progress.statusMessage = TextUtils.formatMessage("Checking '%s' (%d of %d)", currentTask.name, - tasksCompleted + 1, numTasksToComplete); - try { - taskFunction(profile, (result: IProfileValidationTaskResult) => { - result.associatedEndpoints = currentTask.associatedEndpoints; - result.taskName = currentTask.name; - // task is complete, store off the results - tasksCompleted++; - report.taskResults.push(result); - log.debug("Profile validation task result: task name: %s, outcome %s, description %s, associated endpoints: %s", - result.taskName, this.outcomeToString(result.outcome), result.resultDescription, - (result.associatedEndpoints == null ? "none" : result.associatedEndpoints.join(", "))); - - // set the overall status of the validation based on this outcome - // only 100% success is considered a successful validation - if (result.outcome === "Warning" && report.overallResult === "OK") { - report.overallResult = "Warning"; - - } else if (result.outcome === "Failed") { - // mark the validation failed if any task fails - report.overallResult = "Failed"; - } - if (!(currentTask.dependentTasks == null)) { - if (result.outcome === "Failed" || result.outcome === "Warning") { - log.warn("Parent task %s failed, skipping dependent tasks", - currentTask.name); - for (const dependent of currentTask.dependentTasks) { - skipDependentTask(dependent, result); - } - } else { - // add the dependent tasks as the next tasks to execute - log.debug("Adding dependent tasks of %s to the lists of tasks to run", - currentTask.name); - tasksToRun = currentTask.dependentTasks.concat(tasksToRun); - } - } - if (tasksCompleted < numTasksToComplete) { - // if there are more tasks, run the next one - runTask(); - } else { - log.info("All profile validation tasks have completed. The profile's validity: %s", - this.outcomeToString(report.overallResult)); - validationComplete(report); - } - }); - } - /** - * Catch unexpected exceptions within the task function - */ catch (e) { - tasksCompleted++; - report.overallResult = "Failed"; - log.error("Error during profile validation: %s\n%s", e.message, e.stack); - const result: IProfileValidationTaskResult = { - outcome: "Failed", - resultDescription: "Encountered an unexpected exception: " + e.message, - associatedEndpoints: currentTask.associatedEndpoints, - taskName: currentTask.taskName - }; - report.taskResults.push(result); - log.warn("Parent task %s failed, skipping dependent tasks", - currentTask.name); - for (const dependent of currentTask.dependentTasks) { - skipDependentTask(dependent, result); - } - if (tasksCompleted < numTasksToComplete) { - // if there are more tasks, run the next one - runTask(); - } else { - log.info("All profile validation tasks have completed. The profile's validity: %s", - this.outcomeToString(report.overallResult)); - validationComplete(report); - } - - } - }; - runTask(); - }); - - promise.progress = progress; - return promise; - } - - /** - * Get a printed/tabular version of your validation report - * @param {IProfileValidationReport} report - your completed validation result - * @param plan - the validation plan to use - * @param productDisplayName - the display name for your CLI used in the final result text - * @param primaryHighlightColor - color used to highlight headings and tables (used with chalk package) - * @param profileName - the name of the profile that was validated - * @param profileType - the type of the profile that was validated - * @returns {string} - the formatted report - */ - public static getTextDisplayForReport(report: IProfileValidationReport, plan: IProfileValidationPlan, - productDisplayName: string, primaryHighlightColor: string, - profileName: string, profileType: string): string { - const log = Logger.getImperativeLogger(); - let text = ""; - - let {failed, undetermined, succeeded} = this.countOutcomes(report); - - text += CliUtils.formatHelpHeader("Profile Summary", undefined, primaryHighlightColor) + "\n\n"; - const censoredProfile = LoggerUtils.censorYargsArguments(report.profile as any); - text += TextUtils.prettyJson(censoredProfile); - text += CliUtils.formatHelpHeader("Profile Validation Results", undefined, primaryHighlightColor) + "\n\n"; - - /** - * Get a colored summary of the total numbers of failed, warning, and succeeded tests - */ - if (failed === 0) { - failed = TextUtils.chalk.gray(failed); - } else { - failed = TextUtils.chalk.red(failed); - } - if (undetermined === 0) { - undetermined = TextUtils.chalk.gray(undetermined); - } else { - undetermined = TextUtils.chalk.yellow(undetermined); - } - if (succeeded === 0) { - succeeded = TextUtils.chalk.gray(succeeded); - } else { - succeeded = TextUtils.chalk.green(succeeded); - } - - interface ITaskResultRow { - Task: string; - Status: string; - Description: string; - Endpoint: string; - } - - const tableObject: ITaskResultRow[] = report.taskResults.map((taskResult) => { - let statusChar = ""; - if (taskResult.outcome === "OK") { - statusChar = TextUtils.chalk.green("OK"); - } else if (taskResult.outcome === "Warning") { - statusChar = TextUtils.chalk.yellow("?\nWarning"); - } else if (taskResult.outcome === "Failed") { - statusChar = TextUtils.chalk.red("X\nFailed"); - } - let description = taskResult.resultDescription; - const maxDescriptionLength = 500; - if (description.length > maxDescriptionLength) { - description = description.substring(0, maxDescriptionLength) + "...(more info in log)"; - log.info("Truncated description from profile validation: %s", taskResult.resultDescription); - } - const result = { - Task: taskResult.taskName, - Status: statusChar, - Description: description, - Endpoint: taskResult.associatedEndpoints ? taskResult.associatedEndpoints.join(", ") : undefined - }; - if (result.Endpoint == null) { - // this prevents the endpoint column from showing up - // if there are no endpoints specified - delete result.Endpoint; - } - return result; - }); - text += TextUtils.getTable(tableObject, primaryHighlightColor, undefined, true, true, true) + "\n\n"; - text += TextUtils.wordWrap(TextUtils.formatMessage("Of %s tests, %s succeeded, %s failed, and %s had warnings or undetermined results.\n\n", - report.taskResults.length, succeeded, failed, undetermined)); - - if (report.overallResult === "OK") { - text += TextUtils.chalk.green(" *~~ Perfect score! Wow! ~~* ") + "\n\n"; - } - let outcomeMessage = ""; - switch (report.overallResult) { - case "OK": - outcomeMessage = "is valid and ready for use with " + productDisplayName + ".\n All profile validation tests " + - "succeeded."; - break; - case "Failed": - outcomeMessage = "will not function fully with " + productDisplayName + ".\nAt least one of the above " + - "tests failed. " + (plan.failureSuggestions ? "\n" + plan.failureSuggestions : ""); - break; - case "Warning": - outcomeMessage = "might not function properly with " + productDisplayName + ".\nAt least one of the above " + - "tests got ambiguous results. " + (plan.failureSuggestions ? "\n" + plan.failureSuggestions : ""); - break; - default: - log.warn("Unknown validation outcome in report for %s profile %s", profileType, profileName); - } - - text += TextUtils.wordWrap(TextUtils.formatMessage("The %s profile named \"%s\" %s\n", - profileType + "", profileName + "", outcomeMessage)); - return text; - } - - /** - * Get a printed/tabular version of your validation plan, - * so that the user can see what steps the Brightside CLI will take to validate their profile - * @param {IProfileValidationPlan} plan - the plan for profile validation - * @param profile - the profile that would be validated - used only in this case to show a summary of the profile's contents - * @param primaryHighlightColor - primary highlight color for use with chalk - * @returns {string} - the formatted report - */ - public static getTextDisplayForPlan(plan: IProfileValidationPlan, profile: IProfile, primaryHighlightColor: string): string { - let text = ""; - - text += CliUtils.formatHelpHeader("Profile Summary", undefined, primaryHighlightColor) + "\n\n"; - const censoredProfile = LoggerUtils.censorYargsArguments(profile as any); - text += TextUtils.prettyJson(censoredProfile); - text += CliUtils.formatHelpHeader("Profile Validation Plan", undefined, primaryHighlightColor) + "\n\n"; - - /** - * Collapse the tree of task dependencies into a 1D array - * so that we can display it in the table - */ - const allTasks: IProfileValidationTask[] = []; - const addTasks = (task: IProfileValidationTask) => { - allTasks.push(task); - if (!(task.dependentTasks == null)) { - for (const dependent of task.dependentTasks) { - addTasks(dependent); - } - } - }; - for (const task of plan.tasks) { - addTasks(task); - } - - interface ITaskPlanRow { - Task: string; - Description: string; - Endpoints: string; - } - - const tableObject: ITaskPlanRow[] = allTasks.map((task) => { - const result: ITaskPlanRow = { - Task: task.name, - Description: task.description, - Endpoints: task.associatedEndpoints ? task.associatedEndpoints.join(", ") : undefined - }; - if (result.Endpoints == null) { - delete result.Endpoints; - } - return result; - }); - text += TextUtils.getTable(tableObject, primaryHighlightColor, undefined, - true, true) + "\n\n"; - return text; - } - - /** - * Get a more readable version of the outcome - * @param {VALIDATION_OUTCOME} outcome - the outcome to convert to readable version - * @returns {string} - full version of the outcome - */ - public static outcomeToString(outcome: VALIDATION_OUTCOME): string { - if (outcome === "OK") { - return "Succeeded"; - } else if (outcome === "Warning") { - return "Warning"; - } else if (outcome === "Failed") { - return "Failed"; - } - } - - /** - * Get the total number of each type of profile validation outcome - * @param {IProfileValidationReport} report - the report from which - * @returns {{succeeded: number, undetermined: number, failed: number}} - total count - * of what has succeeded, undetermined, failed - */ - private static countOutcomes(report: IProfileValidationReport): { succeeded: number, undetermined: number, failed: number } { - const log = Logger.getImperativeLogger(); - const result = {succeeded: 0, undetermined: 0, failed: 0}; - for (const task of report.taskResults) { - switch (task.outcome) { - case "OK": - result.succeeded++; - break; - case "Warning": - result.undetermined++; - break; - case "Failed": - result.failed++; - break; - default: - log.warn("Unknown validation outcome for %s profile %s", report.profile.type, report.profile.name); - } - } - return result; - } -} diff --git a/packages/imperative/src/profiles/src/validation/doc/IProfileValidationPlan.ts b/packages/imperative/src/profiles/src/validation/doc/IProfileValidationPlan.ts deleted file mode 100644 index f6aaf1dd47..0000000000 --- a/packages/imperative/src/profiles/src/validation/doc/IProfileValidationPlan.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IProfileValidationTask } from "./IProfileValidationTask"; - -/** - * An overall plan for validating a profile, composed of multiple tasks - */ -export interface IProfileValidationPlan { - /** - * The tasks to run to validate the profile. - * They will be run sequentially in the order specified. - */ - tasks: IProfileValidationTask[]; - - /** - * Suggestions to the user that will be displayed in the validation - * report in the event profile validation is not successful. - */ - failureSuggestions?: string; -} diff --git a/packages/imperative/src/profiles/src/validation/doc/IProfileValidationReport.ts b/packages/imperative/src/profiles/src/validation/doc/IProfileValidationReport.ts deleted file mode 100644 index 6c5d02fdd9..0000000000 --- a/packages/imperative/src/profiles/src/validation/doc/IProfileValidationReport.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IProfileValidationTaskResult } from "./IProfileValidationTaskResult"; -import { VALIDATION_OUTCOME } from "./IProfileValidationTask"; -import { IProfile } from "../../doc/definition/IProfile"; - -/** - * Complete report of the results of profile validation - */ -export interface IProfileValidationReport { - /** - * Is the profile valid overall? - */ - overallResult: VALIDATION_OUTCOME; - /** - * A final message explaining the general result of the report - */ - overallMessage: string; - /** - * List of detailed task results from running the profile validation - */ - taskResults: IProfileValidationTaskResult[]; - /** - * The profile that was validated - */ - profile: IProfile; -} diff --git a/packages/imperative/src/profiles/src/validation/doc/IProfileValidationTask.ts b/packages/imperative/src/profiles/src/validation/doc/IProfileValidationTask.ts deleted file mode 100644 index 40a001cb6c..0000000000 --- a/packages/imperative/src/profiles/src/validation/doc/IProfileValidationTask.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { IProfileValidationTaskResult } from "./IProfileValidationTaskResult"; - -export type VALIDATION_OUTCOME = "Failed" | "OK" | "Warning"; - -/** - * A function that takes a profile and calls a done callback with the result of the - * profile validation - */ -export type IProfileValidationTaskFunction = (profile: any, - done: (result: IProfileValidationTaskResult) => void) => void; - -/** - * Criterion/task used for testing the validity of a profile - * You can use any number of these criteria to test different - * aspects of the profile - */ -export interface IProfileValidationTask { - /** - * Long form description of the task you'll take using the - * specified profile to test its validity - */ - description: string; - /** - * The short name of a task e.g. "Submitting a job" - */ - name: string; - /** - * The REST endpoints associated with this task if any, - * e.g. ["PUT /zosmf/restjobs/jobs", "GET /zosmf/restjobs/jobs"] - */ - associatedEndpoints?: string[]; - /** - * A function which tests the profile with your tasks - * Ultimately the result of this function is what determines whether - * the profile is valid or not for this task - */ - taskFunction: IProfileValidationTaskFunction; - - /** - * Any tasks you would like to only run if the current task succeeds - * (skipped on warning or failure of this, the parent task) - */ - dependentTasks?: IProfileValidationTask[]; -} diff --git a/packages/imperative/src/profiles/src/validation/doc/IProfileValidationTaskResult.ts b/packages/imperative/src/profiles/src/validation/doc/IProfileValidationTaskResult.ts deleted file mode 100644 index 3182fbb878..0000000000 --- a/packages/imperative/src/profiles/src/validation/doc/IProfileValidationTaskResult.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -/** - * A single result in the report from testing a profile against an IProfileValidationCriterion - * Used to build the final validation report - */ -import { VALIDATION_OUTCOME } from "./IProfileValidationTask"; - -/** - * Profile validation results for one particular task - */ -export interface IProfileValidationTaskResult { - /** - * Outcome of this task, whether it succeeded, failed, or somewhere in between - */ - outcome: VALIDATION_OUTCOME; - /** - * Name of the task - * (will be automatically populated by the validation API) - */ - taskName?: string; - /** - * A description of the result of the validation test, whether - * it succeeded or failed. Example: - * Successfully submitted job USER(JOB00001) - * or - * Failed to submit job due to the following error: - * Input was not recognized by the system as a job RC 4 RSN ... - */ - resultDescription: string; - /** - * Same as the endpoints in the profile validation task. - * (will be automatically populated by the validation API) - */ - associatedEndpoints?: string[]; -} - diff --git a/packages/imperative/src/rest/__tests__/client/AbstractRestClient.unit.test.ts b/packages/imperative/src/rest/__tests__/client/AbstractRestClient.unit.test.ts index 17a19e4db1..d77a854961 100644 --- a/packages/imperative/src/rest/__tests__/client/AbstractRestClient.unit.test.ts +++ b/packages/imperative/src/rest/__tests__/client/AbstractRestClient.unit.test.ts @@ -18,7 +18,7 @@ import { } from "../../src/session/SessConstants"; import { RestClient } from "../../src/client/RestClient"; import { Headers } from "../../src/client/Headers"; -import { NextVerFeatures, ProcessUtils } from "../../../utilities"; +import { ProcessUtils } from "../../../utilities"; import { MockHttpRequestResponse } from "./__model__/MockHttpRequestResponse"; import { EventEmitter } from "events"; import { ImperativeError } from "../../../error"; @@ -31,7 +31,7 @@ import { AbstractRestClient } from "../../src/client/AbstractRestClient"; import * as os from "os"; import { join } from "path"; import { IO } from "../../../io"; -import { Proxy } from "../../src/client/Proxy"; +import { ProxySettings } from "../../src/client/ProxySettings"; import { HttpsProxyAgent } from "https-proxy-agent"; /** @@ -43,11 +43,6 @@ describe("AbstractRestClient tests", () => { let setPasswordAuthSpy: any; beforeEach(() => { - /* This avoids having to mock ImperativeConfig.envVariablePrefix. - * Unless overridden, tests will use our legacy format for errors. - */ - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(false); - // pretend that basic auth was successfully set setPasswordAuthSpy = jest.spyOn(AbstractRestClient.prototype as any, "setPasswordAuth"); setPasswordAuthSpy.mockReturnValue(true); @@ -190,61 +185,6 @@ describe("AbstractRestClient tests", () => { }); it("should error with request rejection when status code is not in 200 range", async () => { - - interface IResponseload { - newData: string; - } - - const emitter = new MockHttpRequestResponse(); - const requestFnc = jest.fn((options, callback) => { - ProcessUtils.nextTick(async () => { - - const newEmit = new MockHttpRequestResponse(); - newEmit.statusCode = "400"; - callback(newEmit); - - await ProcessUtils.nextTick(() => { - newEmit.emit("data", Buffer.from("{\"newData\":", "utf8")); - }); - - // missing closing bracket - await ProcessUtils.nextTick(() => { - newEmit.emit("data", Buffer.from("\"response data\"}", "utf8")); - }); - - await ProcessUtils.nextTick(() => { - newEmit.emit("end"); - }); - }); - return emitter; - }); - - (https.request as any) = requestFnc; - const headers: any = [{"My-Header": "value is here"}]; - const payload: any = {"my payload object": "hello"}; - let error; - try { - await RestClient.putExpectJSON(new Session({hostname: "test"}), "/resource", headers, payload); - } catch (thrownError) { - error = thrownError; - } - expect(error instanceof ImperativeError).toBe(true); - expect(error.message).toBe("Rest API failure with HTTP(S) status 400"); - expect(error.errorCode).toBe("400"); - expect(error.causeErrors).toBe("{\"newData\":\"response data\"}"); - for (const header of headers) { - // make sure the error contains the headers that were appended to the request - for (const key of Object.keys(header)) { - expect(error.additionalDetails).toContain(key); - expect(error.additionalDetails).toContain(header[key]); - } - } - expect(error.additionalDetails).toContain("HTTP(S) error status \"400\" received."); - }); - - it("should give a v3-format error when status code is not in 200 range", async () => { - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(true); - interface IResponseload { newData: string; } @@ -522,8 +462,8 @@ describe("AbstractRestClient tests", () => { error = thrownError; } - expect(httpRequestFnc).toBeCalled(); - expect(httpsRequestFnc).not.toBeCalled(); + expect(httpRequestFnc).toHaveBeenCalled(); + expect(httpsRequestFnc).not.toHaveBeenCalled(); }); it("should call https request for https requests", async () => { @@ -557,8 +497,8 @@ describe("AbstractRestClient tests", () => { } catch (thrownError) { error = thrownError; } - expect(httpsRequestFnc).toBeCalled(); - expect(httpRequestFnc).not.toBeCalled(); + expect(httpsRequestFnc).toHaveBeenCalled(); + expect(httpRequestFnc).not.toHaveBeenCalled(); }); it("should not error when streaming data", async () => { @@ -819,7 +759,7 @@ describe("AbstractRestClient tests", () => { } catch (thrownError) { error = thrownError; } - expect(httpsRequestFnc).toBeCalled(); + expect(httpsRequestFnc).toHaveBeenCalled(); }); it("should create buildOptions according to input parameter options 2", async () => { @@ -859,7 +799,7 @@ describe("AbstractRestClient tests", () => { } catch (thrownError) { error = thrownError; } - expect(httpsRequestFnc).toBeCalled(); + expect(httpsRequestFnc).toHaveBeenCalled(); expect(error).toBeDefined(); }); @@ -897,7 +837,7 @@ describe("AbstractRestClient tests", () => { } catch (thrownError) { error = thrownError; } - expect(httpsRequestFnc).not.toBeCalled(); + expect(httpsRequestFnc).not.toHaveBeenCalled(); expect(error.message).toContain("Failed to open one or more PEM certificate files"); }); @@ -1496,8 +1436,8 @@ describe("AbstractRestClient tests", () => { beforeEach(() => { jest.clearAllMocks(); - getSystemProxyUrlSpy = jest.spyOn(Proxy, "getSystemProxyUrl"); - getProxyAgentSpy = jest.spyOn(Proxy, "getProxyAgent"); + getSystemProxyUrlSpy = jest.spyOn(ProxySettings, "getSystemProxyUrl"); + getProxyAgentSpy = jest.spyOn(ProxySettings, "getProxyAgent"); setCertPemAuthSpy = jest.spyOn(privateRestClient, "setCertPemAuth"); }); diff --git a/packages/imperative/src/rest/__tests__/client/Proxy.unit.test.ts b/packages/imperative/src/rest/__tests__/client/ProxySettings.unit.test.ts similarity index 82% rename from packages/imperative/src/rest/__tests__/client/Proxy.unit.test.ts rename to packages/imperative/src/rest/__tests__/client/ProxySettings.unit.test.ts index 1e0bff2a57..68d5291c4b 100644 --- a/packages/imperative/src/rest/__tests__/client/Proxy.unit.test.ts +++ b/packages/imperative/src/rest/__tests__/client/ProxySettings.unit.test.ts @@ -11,7 +11,7 @@ import * as process from "process"; -import { Proxy } from "../../src/client/Proxy"; +import { ProxySettings } from "../../src/client/ProxySettings"; import { HTTPS_PROTOCOL, HTTP_PROTOCOL } from "../../src/session/SessConstants"; import { HttpsProxyAgent } from "https-proxy-agent"; @@ -25,7 +25,7 @@ describe("Proxy tests", () => { port: 443, rejectUnauthorized: false } as ISession; - const privateProxy = Proxy as any; + const privateProxy = ProxySettings as any; const httpUrl = "http://www.zowe.com"; const httpsUrl = "https://www.zowe.com"; const noProxyList = "www.zowe.com, fake.com,ibm.com,broadcom.com "; @@ -44,7 +44,7 @@ describe("Proxy tests", () => { proxyUrl: httpUrl, protocol: HTTP_PROTOCOL }); - expect(JSON.stringify(Proxy.getProxyAgent(session))).toEqual(JSON.stringify(expected)); + expect(JSON.stringify(ProxySettings.getProxyAgent(session))).toEqual(JSON.stringify(expected)); }); it("Should retrieve the HTTPS proxy agent", () => { @@ -53,7 +53,7 @@ describe("Proxy tests", () => { proxyUrl: httpsUrl, protocol: HTTPS_PROTOCOL }); - expect(JSON.stringify(Proxy.getProxyAgent(session))).toEqual(JSON.stringify(expected)); + expect(JSON.stringify(ProxySettings.getProxyAgent(session))).toEqual(JSON.stringify(expected)); }); }); @@ -68,7 +68,7 @@ describe("Proxy tests", () => { proxyUrl: httpsUrl, protocol: HTTPS_PROTOCOL }); - expect(Proxy.getSystemProxyUrl(session)).toEqual(httpsUrl); + expect(ProxySettings.getSystemProxyUrl(session)).toEqual(httpsUrl); }); }); @@ -84,7 +84,7 @@ describe("Proxy tests", () => { protocol: HTTPS_PROTOCOL }; checkUrlSpy.mockReturnValue(httpsUrl); - expect(Proxy["getProxySettings"](session)).toEqual(expected); + expect(ProxySettings["getProxySettings"](session)).toEqual(expected); }); }); @@ -96,7 +96,7 @@ describe("Proxy tests", () => { it("Should return the HTTP environment variables if they exist", () => { const expected = httpUrl; process.env["HTTP_PROXY"] = expected; - expect(Proxy["getHttpEnvVariables"]()).toEqual(expected); + expect(ProxySettings["getHttpEnvVariables"]()).toEqual(expected); process.env["HTTP_PROXY"] = undefined; }); }); @@ -105,7 +105,7 @@ describe("Proxy tests", () => { it("Should match session hostname with no_proxy", () => { const expected = true; process.env["NO_PROXY"] = noProxyList; - expect(Proxy["matchesNoProxySettings"](session)).toEqual(expected); + expect(ProxySettings["matchesNoProxySettings"](session)).toEqual(expected); process.env["NO_PROXY"] = undefined; }); @@ -113,7 +113,7 @@ describe("Proxy tests", () => { const expected = false; process.env["NO_PROXY"] = noProxyList; session.hostname = "microsoft.com"; - expect(Proxy["matchesNoProxySettings"](session)).toEqual(expected); + expect(ProxySettings["matchesNoProxySettings"](session)).toEqual(expected); process.env["NO_PROXY"] = undefined; }); }); diff --git a/packages/imperative/src/rest/__tests__/client/RestClient.unit.test.ts b/packages/imperative/src/rest/__tests__/client/RestClient.unit.test.ts index c58d475999..e4f4b14617 100644 --- a/packages/imperative/src/rest/__tests__/client/RestClient.unit.test.ts +++ b/packages/imperative/src/rest/__tests__/client/RestClient.unit.test.ts @@ -14,7 +14,7 @@ import * as path from "path"; import * as https from "https"; import { Session } from "../../src/session/Session"; import { EventEmitter } from "events"; -import { NextVerFeatures, ProcessUtils } from "../../../utilities"; +import { ProcessUtils } from "../../../utilities"; import { MockHttpRequestResponse } from "./__model__/MockHttpRequestResponse"; import { CustomRestClient } from "./__model__/CustomRestClient"; import { CustomRestClientWithProcessError, EXPECTED_REST_ERROR } from "./__model__/CustomRestClientWithProcessError"; @@ -36,11 +36,6 @@ describe("RestClient tests", () => { beforeEach(() => { jest.clearAllMocks(); - /* This avoids having to mock ImperativeConfig.envVariablePrefix. - * Unless overridden, tests will use our legacy format for errors. - */ - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(false); - // pretend that basic auth was successfully set setPasswordAuthSpy = jest.spyOn(AbstractRestClient.prototype as any, "setPasswordAuth"); setPasswordAuthSpy.mockReturnValue(true); diff --git a/packages/imperative/src/rest/__tests__/client/__model__/MockHttpRequestResponse.ts b/packages/imperative/src/rest/__tests__/client/__model__/MockHttpRequestResponse.ts index defc34175d..5306899a13 100644 --- a/packages/imperative/src/rest/__tests__/client/__model__/MockHttpRequestResponse.ts +++ b/packages/imperative/src/rest/__tests__/client/__model__/MockHttpRequestResponse.ts @@ -10,7 +10,6 @@ */ import { EventEmitter } from "events"; - /** * Simulate http(s).clientRequest or http(s).clientRequest callback invoked * @export diff --git a/packages/imperative/src/rest/__tests__/client/__snapshots__/AbstractRestClient.unit.test.ts.snap b/packages/imperative/src/rest/__tests__/client/__snapshots__/AbstractRestClient.unit.test.ts.snap index 99e9fe281e..99a9a8a8e5 100644 --- a/packages/imperative/src/rest/__tests__/client/__snapshots__/AbstractRestClient.unit.test.ts.snap +++ b/packages/imperative/src/rest/__tests__/client/__snapshots__/AbstractRestClient.unit.test.ts.snap @@ -38,7 +38,7 @@ Object { } `; -exports[`AbstractRestClient tests should give an error message when error event is called 1`] = `"http(s) request error event called"`; +exports[`AbstractRestClient tests should give an error message when error event is called 1`] = `"Failed to send an HTTP request."`; exports[`AbstractRestClient tests should give an error when no resource URI is provided 1`] = `"Expect Error: Required parameter 'resource' must not be blank"`; diff --git a/packages/imperative/src/rest/__tests__/session/ConnectionPropsForSessCfg.unit.test.ts b/packages/imperative/src/rest/__tests__/session/ConnectionPropsForSessCfg.unit.test.ts index d84e3f495d..b1cd0a4993 100644 --- a/packages/imperative/src/rest/__tests__/session/ConnectionPropsForSessCfg.unit.test.ts +++ b/packages/imperative/src/rest/__tests__/session/ConnectionPropsForSessCfg.unit.test.ts @@ -10,6 +10,7 @@ */ jest.mock("../../../logger/src/LoggerUtils"); + import { ConnectionPropsForSessCfg } from "../../src/session/ConnectionPropsForSessCfg"; import { CliUtils } from "../../../utilities/src/CliUtils"; import { ImperativeError } from "../../../error"; @@ -20,7 +21,11 @@ import { join } from "path"; import { ConfigAutoStore } from "../../../config/src/ConfigAutoStore"; import { setupConfigToLoad } from "../../../../__tests__/src/TestUtil"; import { IOverridePromptConnProps } from "../../src/session/doc/IOverridePromptConnProps"; +import { IOptionsForAddConnProps } from "../../src/session/doc/IOptionsForAddConnProps"; +import { ImperativeConfig } from "../../../utilities"; +import { ConfigUtils } from "../../../config/src/ConfigUtils"; import { ISshSession } from "../../../../../zosuss/lib/doc/ISshSession"; + const certFilePath = join( __dirname, "..", @@ -58,12 +63,11 @@ interface extendedSession extends ISession { } describe("ConnectionPropsForSessCfg tests", () => { - afterEach(() => { jest.clearAllMocks(); }); - it("authenticate with user and pass", async() => { + it("authenticate with user and pass", async () => { const initialSessCfg = { rejectUnauthorized: true, }; @@ -73,11 +77,13 @@ describe("ConnectionPropsForSessCfg tests", () => { host: "SomeHost", port: 11, user: "FakeUser", - password: "FakePassword" + password: "FakePassword", }; - const sessCfgWithConnProps = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args - ); + const sessCfgWithConnProps = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args + ); expect(sessCfgWithConnProps.hostname).toBe("SomeHost"); expect(sessCfgWithConnProps.port).toBe(11); expect(sessCfgWithConnProps.user).toBe("FakeUser"); @@ -89,58 +95,68 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("authenticate with user, pass, and tokenType to get token", async() => { + it("authenticate with user, pass, and tokenType to get token", async () => { const initialSessCfg = { hostname: "SomeHost", port: 11, - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", _: [""], user: "FakeUser", password: "FakePassword", - tokenType: SessConstants.TOKEN_TYPE_JWT + tokenType: SessConstants.TOKEN_TYPE_JWT, }; - const sessCfgWithConnProps = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, {requestToken: true} - ); + const sessCfgWithConnProps = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { requestToken: true } + ); expect(sessCfgWithConnProps.hostname).toBe("SomeHost"); expect(sessCfgWithConnProps.user).toBe("FakeUser"); expect(sessCfgWithConnProps.password).toBe("FakePassword"); expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_TOKEN); - expect(sessCfgWithConnProps.tokenType).toBe(SessConstants.TOKEN_TYPE_JWT); + expect(sessCfgWithConnProps.tokenType).toBe( + SessConstants.TOKEN_TYPE_JWT + ); expect(sessCfgWithConnProps.tokenValue).toBeUndefined(); expect(sessCfgWithConnProps.cert).toBeUndefined(); expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("authenticate with user, pass, and *NO* tokenType to get token", async() => { + it("authenticate with user, pass, and *NO* tokenType to get token", async () => { const initialSessCfg = { hostname: "SomeHost", port: 11, - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", _: [""], user: "FakeUser", - password: "FakePassword" + password: "FakePassword", }; - const sessCfgWithConnProps = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, {requestToken: true} - ); + const sessCfgWithConnProps = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { requestToken: true } + ); expect(sessCfgWithConnProps.hostname).toBe("SomeHost"); expect(sessCfgWithConnProps.user).toBe("FakeUser"); expect(sessCfgWithConnProps.password).toBe("FakePassword"); expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_TOKEN); - expect(sessCfgWithConnProps.tokenType).toBe(SessConstants.TOKEN_TYPE_JWT); + expect(sessCfgWithConnProps.tokenType).toBe( + SessConstants.TOKEN_TYPE_JWT + ); expect(sessCfgWithConnProps.tokenValue).toBeUndefined(); expect(sessCfgWithConnProps.cert).toBeUndefined(); expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("authenticate with token value", async() => { + it("authenticate with token value", async () => { const initialSessCfg = { hostname: "SomeHost", port: 11, @@ -151,9 +167,11 @@ describe("ConnectionPropsForSessCfg tests", () => { _: [""], tokenValue: "FakeToken", }; - const sessCfgWithConnProps = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args - ); + const sessCfgWithConnProps = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args + ); expect(sessCfgWithConnProps.hostname).toBe("SomeHost"); expect(sessCfgWithConnProps.tokenValue).toBe("FakeToken"); expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_BEARER); @@ -163,48 +181,56 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("authenticate with token value and token type", async() => { + it("authenticate with token value and token type", async () => { const initialSessCfg = { hostname: "SomeHost", port: 11, - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", _: [""], tokenValue: "FakeToken", - tokenType: SessConstants.TOKEN_TYPE_LTPA + tokenType: SessConstants.TOKEN_TYPE_LTPA, }; - const sessCfgWithConnProps = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args - ); + const sessCfgWithConnProps = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args + ); expect(sessCfgWithConnProps.hostname).toBe("SomeHost"); expect(sessCfgWithConnProps.tokenValue).toBe("FakeToken"); expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_TOKEN); - expect(sessCfgWithConnProps.tokenType).toBe(SessConstants.TOKEN_TYPE_LTPA); + expect(sessCfgWithConnProps.tokenType).toBe( + SessConstants.TOKEN_TYPE_LTPA + ); expect(sessCfgWithConnProps.user).toBeUndefined(); expect(sessCfgWithConnProps.password).toBeUndefined(); expect(sessCfgWithConnProps.cert).toBeUndefined(); expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("authenticate with certFile and certKeyFile", async() => { + it("authenticate with certFile and certKeyFile", async () => { const initialSessCfg = { hostname: "SomeHost", port: 11, - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", _: [""], certFile: certFilePath, - certKeyFile: certKeyFilePath + certKeyFile: certKeyFilePath, }; - const sessCfgWithConnProps = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args - ); + const sessCfgWithConnProps = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args + ); expect(sessCfgWithConnProps.hostname).toBe("SomeHost"); - expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_CERT_PEM); + expect(sessCfgWithConnProps.type).toBe( + SessConstants.AUTH_TYPE_CERT_PEM + ); expect(sessCfgWithConnProps.cert).toBe(certFilePath); expect(sessCfgWithConnProps.certKey).toBe(certKeyFilePath); expect(sessCfgWithConnProps.user).toBeUndefined(); @@ -213,11 +239,11 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.tokenValue).toBeUndefined(); }); - it("ignore token and cert if unsupported auth types and authenticate with user and pass", async() => { + it("ignore token and cert if unsupported auth types and authenticate with user and pass", async () => { const initialSessCfg = { hostname: "SomeHost", port: 11, - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", @@ -225,15 +251,18 @@ describe("ConnectionPropsForSessCfg tests", () => { cert: "fakeCert", certKey: "fakeCertKey", tokenType: SessConstants.TOKEN_TYPE_JWT, - tokenValue: "fakeToken" + tokenValue: "fakeToken", }; const fakePromptFn = jest.fn().mockReturnValue({ - "user": "FakeUser", - "password": "FakePassword" + user: "FakeUser", + password: "FakePassword", }); - const sessCfgWithConnProps = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, {getValuesBack: fakePromptFn, supportedAuthTypes: ["basic"]} - ); + const sessCfgWithConnProps = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { getValuesBack: fakePromptFn, supportedAuthTypes: ["basic"] } + ); expect(fakePromptFn).toHaveBeenCalledWith(["user", "password"]); expect(sessCfgWithConnProps.hostname).toBe("SomeHost"); expect(sessCfgWithConnProps.user).toBe("FakeUser"); @@ -241,11 +270,11 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_BASIC); }); - it("not set tokenValue if user and pass are defined", async() => { + it("not set tokenValue if user and pass are defined", async () => { const initialSessCfg = { hostname: "SomeHost", port: 11, - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", @@ -253,11 +282,13 @@ describe("ConnectionPropsForSessCfg tests", () => { user: "FakeUser", password: "FakePassword", tokenType: SessConstants.TOKEN_TYPE_JWT, - tokenValue: "FakeToken" + tokenValue: "FakeToken", }; - const sessCfgWithConnProps = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args - ); + const sessCfgWithConnProps = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args + ); expect(sessCfgWithConnProps.hostname).toBe("SomeHost"); expect(sessCfgWithConnProps.user).toBe("FakeUser"); expect(sessCfgWithConnProps.password).toBe("FakePassword"); @@ -268,20 +299,23 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("not prompt when asked not to prompt", async() => { + it("not prompt when asked not to prompt", async () => { const initialSessCfg = { hostname: "SomeHost", port: 11, - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", - _: [""] + _: [""], }; - const sessCfgWithConnProps: ISession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, {doPrompting: false} - ); + const sessCfgWithConnProps: ISession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { doPrompting: false } + ); expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_BASIC); expect(sessCfgWithConnProps.user).toBeUndefined(); expect(sessCfgWithConnProps.password).toBeUndefined(); @@ -291,32 +325,37 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("override with a different command line name", async() => { + it("override with a different command line name", async () => { const passFromPrompt = "somePass"; const initialSessCfg: extendedSession = { hostname: "SomeHost", port: 11, user: "FakeUser", password: "somePass", - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", _: [""], - someKeyOther: "somekeyvalue" - }; - const overrides: IOverridePromptConnProps[] = [{ - propertyName: "someKey", - argumentName: "someKeyOther", - propertiesOverridden: [ - "password", - "tokenType", - "tokenValue", - "cert", - "certKey" - ] - }]; - const mockClientPrompt = jest.spyOn(ConnectionPropsForSessCfg as any, "clientPrompt"); + someKeyOther: "somekeyvalue", + }; + const overrides: IOverridePromptConnProps[] = [ + { + propertyName: "someKey", + argumentName: "someKeyOther", + propertiesOverridden: [ + "password", + "tokenType", + "tokenValue", + "cert", + "certKey", + ], + }, + ]; + const mockClientPrompt = jest.spyOn( + ConnectionPropsForSessCfg as any, + "clientPrompt" + ); // command handler prompt method (CLI versus SDK-based prompting) const commandHandlerPrompt = jest.fn(() => { return Promise.resolve(passFromPrompt); @@ -325,16 +364,23 @@ describe("ConnectionPropsForSessCfg tests", () => { const parms = { response: { console: { - prompt: commandHandlerPrompt - } - } + prompt: commandHandlerPrompt, + }, + }, }; - const sessCfgWithConnProps: extendedSession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, {doPrompting: true, propertyOverrides: overrides, parms: (parms as any)} - ); + const sessCfgWithConnProps: extendedSession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { + doPrompting: true, + propertyOverrides: overrides, + parms: parms as any, + } + ); expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_BASIC); - expect(commandHandlerPrompt).not.toBeCalled(); // we are only testing that we call an already tested prompt method if in CLI mode - expect(mockClientPrompt).not.toBeCalled(); + expect(commandHandlerPrompt).not.toHaveBeenCalled(); // we are only testing that we call an already tested prompt method if in CLI mode + expect(mockClientPrompt).not.toHaveBeenCalled(); expect(sessCfgWithConnProps.user).toEqual("FakeUser"); expect(sessCfgWithConnProps.someKey).toEqual("somekeyvalue"); expect(sessCfgWithConnProps.password).toBeUndefined(); @@ -344,31 +390,36 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("override a session value when an override is specified on the command line", async() => { + it("override a session value when an override is specified on the command line", async () => { const passFromPrompt = "somePass"; const initialSessCfg: extendedSession = { hostname: "SomeHost", port: 11, user: "FakeUser", password: "somePass", - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", _: [""], - someKey: "somekeyvalue" - }; - const overrides: IOverridePromptConnProps[] = [{ - propertyName: "someKey", - propertiesOverridden: [ - "password", - "tokenType", - "tokenValue", - "cert", - "certKey" - ] - }]; - const mockClientPrompt = jest.spyOn(ConnectionPropsForSessCfg as any, "clientPrompt"); + someKey: "somekeyvalue", + }; + const overrides: IOverridePromptConnProps[] = [ + { + propertyName: "someKey", + propertiesOverridden: [ + "password", + "tokenType", + "tokenValue", + "cert", + "certKey", + ], + }, + ]; + const mockClientPrompt = jest.spyOn( + ConnectionPropsForSessCfg as any, + "clientPrompt" + ); // command handler prompt method (CLI versus SDK-based prompting) const commandHandlerPrompt = jest.fn(() => { return Promise.resolve(passFromPrompt); @@ -377,16 +428,23 @@ describe("ConnectionPropsForSessCfg tests", () => { const parms = { response: { console: { - prompt: commandHandlerPrompt - } - } + prompt: commandHandlerPrompt, + }, + }, }; - const sessCfgWithConnProps: extendedSession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, {doPrompting: true, propertyOverrides: overrides, parms: (parms as any)} - ); + const sessCfgWithConnProps: extendedSession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { + doPrompting: true, + propertyOverrides: overrides, + parms: parms as any, + } + ); expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_BASIC); - expect(commandHandlerPrompt).not.toBeCalled(); // we are only testing that we call an already tested prompt method if in CLI mode - expect(mockClientPrompt).not.toBeCalled(); + expect(commandHandlerPrompt).not.toHaveBeenCalled(); // we are only testing that we call an already tested prompt method if in CLI mode + expect(mockClientPrompt).not.toHaveBeenCalled(); expect(sessCfgWithConnProps.user).toEqual("FakeUser"); expect(sessCfgWithConnProps.someKey).toEqual("somekeyvalue"); expect(sessCfgWithConnProps.password).toBeUndefined(); @@ -396,7 +454,7 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("override a session value when an override is specified on the session", async() => { + it("override a session value when an override is specified on the session", async () => { const passFromPrompt = "somePass"; const initialSessCfg: extendedSession = { hostname: "SomeHost", @@ -404,23 +462,28 @@ describe("ConnectionPropsForSessCfg tests", () => { user: "FakeUser", password: "somePass", someKey: "somekeyvalue", - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", - _: [""] - }; - const overrides: IOverridePromptConnProps[] = [{ - propertyName: "someKey", - propertiesOverridden: [ - "password", - "tokenType", - "tokenValue", - "cert", - "certKey" - ] - }]; - const mockClientPrompt = jest.spyOn(ConnectionPropsForSessCfg as any, "clientPrompt"); + _: [""], + }; + const overrides: IOverridePromptConnProps[] = [ + { + propertyName: "someKey", + propertiesOverridden: [ + "password", + "tokenType", + "tokenValue", + "cert", + "certKey", + ], + }, + ]; + const mockClientPrompt = jest.spyOn( + ConnectionPropsForSessCfg as any, + "clientPrompt" + ); // command handler prompt method (CLI versus SDK-based prompting) const commandHandlerPrompt = jest.fn(() => { return Promise.resolve(passFromPrompt); @@ -429,16 +492,23 @@ describe("ConnectionPropsForSessCfg tests", () => { const parms = { response: { console: { - prompt: commandHandlerPrompt - } - } + prompt: commandHandlerPrompt, + }, + }, }; - const sessCfgWithConnProps: extendedSession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, {doPrompting: true, propertyOverrides: overrides, parms: (parms as any)} - ); + const sessCfgWithConnProps: extendedSession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { + doPrompting: true, + propertyOverrides: overrides, + parms: parms as any, + } + ); expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_BASIC); - expect(commandHandlerPrompt).not.toBeCalled(); // we are only testing that we call an already tested prompt method if in CLI mode - expect(mockClientPrompt).not.toBeCalled(); + expect(commandHandlerPrompt).not.toHaveBeenCalled(); // we are only testing that we call an already tested prompt method if in CLI mode + expect(mockClientPrompt).not.toHaveBeenCalled(); expect(sessCfgWithConnProps.user).toEqual("FakeUser"); expect(sessCfgWithConnProps.someKey).toEqual("somekeyvalue"); expect(sessCfgWithConnProps.password).toBeUndefined(); @@ -448,30 +518,35 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("not prompt when an override is specified on the command line", async() => { + it("not prompt when an override is specified on the command line", async () => { const passFromPrompt = "somePass"; const initialSessCfg: extendedSession = { hostname: "SomeHost", port: 11, user: "FakeUser", - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", _: [""], - someKey: "somekeyvalue" - }; - const overrides: IOverridePromptConnProps[] = [{ - propertyName: "someKey", - propertiesOverridden: [ - "password", - "tokenType", - "tokenValue", - "cert", - "certKey" - ] - }]; - const mockClientPrompt = jest.spyOn(ConnectionPropsForSessCfg as any, "clientPrompt"); + someKey: "somekeyvalue", + }; + const overrides: IOverridePromptConnProps[] = [ + { + propertyName: "someKey", + propertiesOverridden: [ + "password", + "tokenType", + "tokenValue", + "cert", + "certKey", + ], + }, + ]; + const mockClientPrompt = jest.spyOn( + ConnectionPropsForSessCfg as any, + "clientPrompt" + ); // command handler prompt method (CLI versus SDK-based prompting) const commandHandlerPrompt = jest.fn(() => { return Promise.resolve(passFromPrompt); @@ -480,16 +555,23 @@ describe("ConnectionPropsForSessCfg tests", () => { const parms = { response: { console: { - prompt: commandHandlerPrompt - } - } + prompt: commandHandlerPrompt, + }, + }, }; - const sessCfgWithConnProps: extendedSession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, {doPrompting: true, propertyOverrides: overrides, parms: (parms as any)} - ); + const sessCfgWithConnProps: extendedSession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { + doPrompting: true, + propertyOverrides: overrides, + parms: parms as any, + } + ); expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_BASIC); - expect(commandHandlerPrompt).not.toBeCalled(); // we are only testing that we call an already tested prompt method if in CLI mode - expect(mockClientPrompt).not.toBeCalled(); + expect(commandHandlerPrompt).not.toHaveBeenCalled(); // we are only testing that we call an already tested prompt method if in CLI mode + expect(mockClientPrompt).not.toHaveBeenCalled(); expect(sessCfgWithConnProps.user).toEqual("FakeUser"); expect(sessCfgWithConnProps.someKey).toEqual("somekeyvalue"); expect(sessCfgWithConnProps.password).toBeUndefined(); @@ -499,30 +581,35 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("not prompt when an override is specified on the session", async() => { + it("not prompt when an override is specified on the session", async () => { const passFromPrompt = "somePass"; const initialSessCfg: extendedSession = { hostname: "SomeHost", port: 11, user: "FakeUser", rejectUnauthorized: true, - someKey: "somekeyvalue" + someKey: "somekeyvalue", }; const args = { $0: "zowe", - _: [""] - }; - const overrides: IOverridePromptConnProps[] = [{ - propertyName: "someKey", - propertiesOverridden: [ - "password", - "tokenType", - "tokenValue", - "cert", - "certKey" - ] - }]; - const mockClientPrompt = jest.spyOn(ConnectionPropsForSessCfg as any, "clientPrompt"); + _: [""], + }; + const overrides: IOverridePromptConnProps[] = [ + { + propertyName: "someKey", + propertiesOverridden: [ + "password", + "tokenType", + "tokenValue", + "cert", + "certKey", + ], + }, + ]; + const mockClientPrompt = jest.spyOn( + ConnectionPropsForSessCfg as any, + "clientPrompt" + ); // command handler prompt method (CLI versus SDK-based prompting) const commandHandlerPrompt = jest.fn(() => { return Promise.resolve(passFromPrompt); @@ -531,16 +618,23 @@ describe("ConnectionPropsForSessCfg tests", () => { const parms = { response: { console: { - prompt: commandHandlerPrompt - } - } + prompt: commandHandlerPrompt, + }, + }, }; - const sessCfgWithConnProps: extendedSession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, {doPrompting: true, propertyOverrides: overrides, parms: (parms as any)} - ); + const sessCfgWithConnProps: extendedSession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { + doPrompting: true, + propertyOverrides: overrides, + parms: parms as any, + } + ); expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_BASIC); - expect(commandHandlerPrompt).not.toBeCalled(); // we are only testing that we call an already tested prompt method if in CLI mode - expect(mockClientPrompt).not.toBeCalled(); + expect(commandHandlerPrompt).not.toHaveBeenCalled(); // we are only testing that we call an already tested prompt method if in CLI mode + expect(mockClientPrompt).not.toHaveBeenCalled(); expect(sessCfgWithConnProps.user).toEqual("FakeUser"); expect(sessCfgWithConnProps.someKey).toEqual("somekeyvalue"); expect(sessCfgWithConnProps.password).toBeUndefined(); @@ -550,29 +644,34 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("should prompt when an override is specified but is not present", async() => { + it("should prompt when an override is specified but is not present", async () => { const passFromPrompt = "somePass"; const initialSessCfg: extendedSession = { hostname: "SomeHost", port: 11, user: "FakeUser", - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", - _: [""] - }; - const overrides: IOverridePromptConnProps[] = [{ - propertyName: "someKey", - propertiesOverridden: [ - "password", - "tokenType", - "tokenValue", - "cert", - "certKey" - ] - }]; - const mockClientPrompt = jest.spyOn(ConnectionPropsForSessCfg as any, "clientPrompt"); + _: [""], + }; + const overrides: IOverridePromptConnProps[] = [ + { + propertyName: "someKey", + propertiesOverridden: [ + "password", + "tokenType", + "tokenValue", + "cert", + "certKey", + ], + }, + ]; + const mockClientPrompt = jest.spyOn( + ConnectionPropsForSessCfg as any, + "clientPrompt" + ); // command handler prompt method (CLI versus SDK-based prompting) const commandHandlerPrompt = jest.fn(() => { return Promise.resolve(passFromPrompt); @@ -581,15 +680,22 @@ describe("ConnectionPropsForSessCfg tests", () => { const parms = { response: { console: { - prompt: commandHandlerPrompt - } - } + prompt: commandHandlerPrompt, + }, + }, }; - const sessCfgWithConnProps: extendedSession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, {doPrompting: true, propertyOverrides: overrides, parms: (parms as any)} - ); + const sessCfgWithConnProps: extendedSession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { + doPrompting: true, + propertyOverrides: overrides, + parms: parms as any, + } + ); expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_BASIC); - expect(commandHandlerPrompt).toBeCalled(); // we are only testing that we call an already tested prompt method if in CLI mode + expect(commandHandlerPrompt).toHaveBeenCalled(); // we are only testing that we call an already tested prompt method if in CLI mode expect((mockClientPrompt.mock.calls[0][1] as any).parms).toBe(parms); expect(sessCfgWithConnProps.user).toEqual("FakeUser"); expect(sessCfgWithConnProps.someKey).toBeUndefined(); @@ -600,31 +706,36 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("not prompt when an override is specified and should prioritize the argument value", async() => { + it("not prompt when an override is specified and should prioritize the argument value", async () => { const passFromPrompt = "somePass"; const initialSessCfg: extendedSession = { hostname: "SomeHost", port: 11, user: "FakeUser", rejectUnauthorized: true, - someKey: "somekeyvalue" + someKey: "somekeyvalue", }; const args = { $0: "zowe", _: [""], - someKey: "someotherkeyvalue" - }; - const overrides: IOverridePromptConnProps[] = [{ - propertyName: "someKey", - propertiesOverridden: [ - "password", - "tokenType", - "tokenValue", - "cert", - "certKey" - ] - }]; - const mockClientPrompt = jest.spyOn(ConnectionPropsForSessCfg as any, "clientPrompt"); + someKey: "someotherkeyvalue", + }; + const overrides: IOverridePromptConnProps[] = [ + { + propertyName: "someKey", + propertiesOverridden: [ + "password", + "tokenType", + "tokenValue", + "cert", + "certKey", + ], + }, + ]; + const mockClientPrompt = jest.spyOn( + ConnectionPropsForSessCfg as any, + "clientPrompt" + ); // command handler prompt method (CLI versus SDK-based prompting) const commandHandlerPrompt = jest.fn(() => { return Promise.resolve(passFromPrompt); @@ -633,16 +744,23 @@ describe("ConnectionPropsForSessCfg tests", () => { const parms = { response: { console: { - prompt: commandHandlerPrompt - } - } + prompt: commandHandlerPrompt, + }, + }, }; - const sessCfgWithConnProps: extendedSession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, {doPrompting: true, propertyOverrides: overrides, parms: (parms as any)} - ); + const sessCfgWithConnProps: extendedSession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { + doPrompting: true, + propertyOverrides: overrides, + parms: parms as any, + } + ); expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_BASIC); - expect(commandHandlerPrompt).not.toBeCalled(); // we are only testing that we call an already tested prompt method if in CLI mode - expect(mockClientPrompt).not.toBeCalled(); + expect(commandHandlerPrompt).not.toHaveBeenCalled(); // we are only testing that we call an already tested prompt method if in CLI mode + expect(mockClientPrompt).not.toHaveBeenCalled(); expect(sessCfgWithConnProps.user).toEqual("FakeUser"); expect(sessCfgWithConnProps.someKey).toEqual("someotherkeyvalue"); expect(sessCfgWithConnProps.password).toBeUndefined(); @@ -652,21 +770,24 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("get user name from prompt from daemon client", async() => { + it("get user name from prompt from daemon client", async () => { const userFromPrompt = "FakeUser"; const passFromArgs = "FakePassword"; - const mockClientPrompt = jest.spyOn(ConnectionPropsForSessCfg as any, "clientPrompt"); + const mockClientPrompt = jest.spyOn( + ConnectionPropsForSessCfg as any, + "clientPrompt" + ); const initialSessCfg = { hostname: "SomeHost", port: 11, - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", _: [""], - password: passFromArgs + password: passFromArgs, }; // command handler prompt method (CLI versus SDK-based prompting) @@ -678,22 +799,25 @@ describe("ConnectionPropsForSessCfg tests", () => { const parms = { response: { console: { - prompt: commandHandlerPrompt - } - } + prompt: commandHandlerPrompt, + }, + }, }; - const sessCfgWithConnProps: ISession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, { - parms: parms as any // treat this as a CLI-based prompt - } - ); + const sessCfgWithConnProps: ISession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { + parms: parms as any, // treat this as a CLI-based prompt + } + ); - expect(commandHandlerPrompt).toBeCalled(); // we are only testing that we call an already tested prompt method if in CLI mode - expect((mockClientPrompt.mock.calls[0][1] as any).parms).toBe(parms); // toBe is important here, parms object must be same as original + expect(commandHandlerPrompt).toHaveBeenCalled(); // we are only testing that we call an already tested prompt method if in CLI mode + expect((mockClientPrompt.mock.calls[0][1] as any).parms).toBe(parms); // toBe is important here, parms object must be same as original }); - it("get user name from prompt", async() => { + it("get user name from prompt", async () => { const userFromPrompt = "FakeUser"; const passFromArgs = "FakePassword"; @@ -707,17 +831,19 @@ describe("ConnectionPropsForSessCfg tests", () => { const initialSessCfg = { hostname: "SomeHost", port: 11, - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", _: [""], - password: passFromArgs + password: passFromArgs, }; - const sessCfgWithConnProps: ISession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args - ); + const sessCfgWithConnProps: ISession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args + ); CliUtils.sleep = sleepReal; CliUtils.readPrompt = readPromptReal; @@ -730,7 +856,7 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("get password from prompt", async() => { + it("get password from prompt", async () => { const userFromArgs = "FakeUser"; const passFromPrompt = "FakePassword"; @@ -744,17 +870,19 @@ describe("ConnectionPropsForSessCfg tests", () => { const initialSessCfg = { hostname: "SomeHost", port: 11, - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", _: [""], - user: userFromArgs + user: userFromArgs, }; - const sessCfgWithConnProps: ISession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args - ); + const sessCfgWithConnProps: ISession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args + ); CliUtils.sleep = sleepReal; CliUtils.readPrompt = readPromptReal; @@ -767,7 +895,7 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("get host name from prompt", async() => { + it("get host name from prompt", async () => { const hostFromPrompt = "FakeHost"; const portFromArgs = 11; const userFromArgs = "FakeUser"; @@ -788,12 +916,14 @@ describe("ConnectionPropsForSessCfg tests", () => { _: [""], port: portFromArgs, user: userFromArgs, - password: passFromArgs + password: passFromArgs, }; - const sessCfgWithConnProps: ISession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args - ); + const sessCfgWithConnProps: ISession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args + ); CliUtils.sleep = sleepReal; CliUtils.readPrompt = readPromptReal; @@ -807,7 +937,7 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("get port from prompt - string", async() => { + it("get port from prompt - string", async () => { const hostFromArgs = "FakeHost"; const portFromPrompt = "11"; const userFromArgs = "FakeUser"; @@ -821,19 +951,21 @@ describe("ConnectionPropsForSessCfg tests", () => { }); const initialSessCfg = { - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", _: [""], host: hostFromArgs, user: userFromArgs, - password: passFromArgs + password: passFromArgs, }; - const sessCfgWithConnProps: ISession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args - ); + const sessCfgWithConnProps: ISession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args + ); CliUtils.sleep = sleepReal; CliUtils.readPrompt = readPromptReal; @@ -846,7 +978,7 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.tokenValue).toBeUndefined(); }); - it("get port from prompt - number", async() => { + it("get port from prompt - number", async () => { const hostFromArgs = "FakeHost"; const portFromPrompt = 11; const userFromArgs = "FakeUser"; @@ -858,24 +990,29 @@ describe("ConnectionPropsForSessCfg tests", () => { CliUtils.readPrompt = jest.fn(() => { return Promise.resolve(portFromPrompt.toString()); }); - jest.spyOn(ConnectionPropsForSessCfg as any, "loadSchemaForSessCfgProps").mockReturnValueOnce({ - port: { type: "number" } + jest.spyOn( + ConnectionPropsForSessCfg as any, + "loadSchemaForSessCfgProps" + ).mockReturnValueOnce({ + port: { type: "number" }, }); const initialSessCfg = { - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", _: [""], host: hostFromArgs, user: userFromArgs, - password: passFromArgs + password: passFromArgs, }; - const sessCfgWithConnProps: ISession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args - ); + const sessCfgWithConnProps: ISession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args + ); CliUtils.sleep = sleepReal; CliUtils.readPrompt = readPromptReal; @@ -888,7 +1025,56 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.tokenValue).toBeUndefined(); }); - it("get host name from prompt with custom service description", async() => { + it("get port from prompt - zero", async () => { + const hostFromArgs = "FakeHost"; + const portFromArgs = 0; + const portFromPrompt = 11; + const userFromArgs = "FakeUser"; + const passFromArgs = "FakePassword"; + + const sleepReal = CliUtils.sleep; + CliUtils.sleep = jest.fn(); + const readPromptReal = CliUtils.readPrompt; + CliUtils.readPrompt = jest.fn(() => { + return Promise.resolve(portFromPrompt.toString()); + }); + jest.spyOn( + ConnectionPropsForSessCfg as any, + "loadSchemaForSessCfgProps" + ).mockReturnValueOnce({ + port: { type: "number" }, + }); + + const initialSessCfg = { + rejectUnauthorized: true, + }; + const args = { + $0: "zowe", + _: [""], + host: hostFromArgs, + port: portFromArgs, + user: userFromArgs, + password: passFromArgs, + }; + + const sessCfgWithConnProps: ISession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args + ); + CliUtils.sleep = sleepReal; + CliUtils.readPrompt = readPromptReal; + + expect(sessCfgWithConnProps.type).toBe(SessConstants.AUTH_TYPE_BASIC); + expect(sessCfgWithConnProps.user).toBe(userFromArgs); + expect(sessCfgWithConnProps.password).toBe(passFromArgs); + expect(sessCfgWithConnProps.hostname).toBe(hostFromArgs); + expect(sessCfgWithConnProps.port).toBe(portFromPrompt); + expect(sessCfgWithConnProps.tokenType).toBeUndefined(); + expect(sessCfgWithConnProps.tokenValue).toBeUndefined(); + }); + + it("get host name from prompt with custom service description", async () => { const hostFromPrompt = "FakeHost"; const portFromArgs = 11; const userFromArgs = "FakeUser"; @@ -911,12 +1097,15 @@ describe("ConnectionPropsForSessCfg tests", () => { _: [""], port: portFromArgs, user: userFromArgs, - password: passFromArgs + password: passFromArgs, }; - const sessCfgWithConnProps: ISession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, { serviceDescription: "my cool service" } - ); + const sessCfgWithConnProps: ISession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { serviceDescription: "my cool service" } + ); CliUtils.sleep = sleepReal; CliUtils.readPrompt = readPromptReal; @@ -929,7 +1118,7 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.tokenValue).toBeUndefined(); }); - it("get port from prompt with custom service description", async() => { + it("get port from prompt with custom service description", async () => { const hostFromArgs = "FakeHost"; const portFromPrompt = 11; const userFromArgs = "FakeUser"; @@ -943,24 +1132,30 @@ describe("ConnectionPropsForSessCfg tests", () => { questionText = text; return Promise.resolve(portFromPrompt.toString()); }); - jest.spyOn(ConnectionPropsForSessCfg as any, "loadSchemaForSessCfgProps").mockReturnValueOnce({ - port: { type: "number" } + jest.spyOn( + ConnectionPropsForSessCfg as any, + "loadSchemaForSessCfgProps" + ).mockReturnValueOnce({ + port: { type: "number" }, }); const initialSessCfg = { - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", _: [""], host: hostFromArgs, user: userFromArgs, - password: passFromArgs + password: passFromArgs, }; - const sessCfgWithConnProps: ISession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, { serviceDescription: "my cool service" } - ); + const sessCfgWithConnProps: ISession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { serviceDescription: "my cool service" } + ); CliUtils.sleep = sleepReal; CliUtils.readPrompt = readPromptReal; @@ -976,7 +1171,7 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("get host name from prompt with hidden text - service profile", async() => { + it("get host name from prompt with hidden text - service profile", async () => { const hostFromPrompt = "FakeHost"; const portFromArgs = 11; const userFromArgs = "FakeUser"; @@ -992,7 +1187,7 @@ describe("ConnectionPropsForSessCfg tests", () => { _: [""], port: portFromArgs, user: userFromArgs, - password: passFromArgs + password: passFromArgs, }; // command handler prompt method (CLI versus SDK-based prompting) @@ -1007,28 +1202,34 @@ describe("ConnectionPropsForSessCfg tests", () => { arguments: {}, response: { console: { - prompt: commandHandlerPrompt - } - } + prompt: commandHandlerPrompt, + }, + }, }; - jest.spyOn(ConfigAutoStore, "findActiveProfile").mockReturnValueOnce(["fruit", "mango"]); + jest.spyOn(ConfigAutoStore, "findActiveProfile").mockReturnValueOnce([ + "fruit", + "mango", + ]); await setupConfigToLoad({ profiles: { mango: { type: "fruit", properties: {}, - secure: ["host"] - } + secure: ["host"], + }, }, - defaults: { fruit: "mango" } + defaults: { fruit: "mango" }, }); - const sessCfgWithConnProps: ISession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, { - parms: parms as any // treat this as a CLI-based prompt - } - ); + const sessCfgWithConnProps: ISession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { + parms: parms as any, // treat this as a CLI-based prompt + } + ); expect(questionText).toContain("(will be hidden)"); expect(promptOpts.hideText).toBe(true); @@ -1040,7 +1241,7 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.tokenValue).toBeUndefined(); }); - it("get host name from prompt with hidden text - base profile", async() => { + it("get host name from prompt with hidden text - base profile", async () => { const hostFromPrompt = "FakeHost"; const portFromArgs = 11; const userFromArgs = "FakeUser"; @@ -1056,7 +1257,7 @@ describe("ConnectionPropsForSessCfg tests", () => { _: [""], port: portFromArgs, user: userFromArgs, - password: passFromArgs + password: passFromArgs, }; // command handler prompt method (CLI versus SDK-based prompting) @@ -1071,32 +1272,38 @@ describe("ConnectionPropsForSessCfg tests", () => { arguments: {}, response: { console: { - prompt: commandHandlerPrompt - } - } + prompt: commandHandlerPrompt, + }, + }, }; - jest.spyOn(ConfigAutoStore, "findActiveProfile").mockReturnValueOnce(["fruit", "mango"]); + jest.spyOn(ConfigAutoStore, "findActiveProfile").mockReturnValueOnce([ + "fruit", + "mango", + ]); await setupConfigToLoad({ profiles: { mango: { type: "fruit", - properties: {} + properties: {}, }, fruit: { type: "base", properties: {}, - secure: ["host"] - } + secure: ["host"], + }, }, - defaults: { fruit: "mango", base: "fruit" } + defaults: { fruit: "mango", base: "fruit" }, }); - const sessCfgWithConnProps: ISession = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, { - parms: parms as any // treat this as a CLI-based prompt - } - ); + const sessCfgWithConnProps: ISession = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { + parms: parms as any, // treat this as a CLI-based prompt + } + ); expect(questionText).toContain("(will be hidden)"); expect(promptOpts.hideText).toBe(true); @@ -1108,7 +1315,7 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.tokenValue).toBeUndefined(); }); - it("throws an error if user doesn't enter port as a number", async() => { + it("throws an error if user doesn't enter port as a number", async () => { const hostFromArgs = "FakeHost"; const portFromPrompt = "abcd"; const userFromArgs = "FakeUser"; @@ -1120,24 +1327,30 @@ describe("ConnectionPropsForSessCfg tests", () => { CliUtils.readPrompt = jest.fn(() => { return Promise.resolve(portFromPrompt); }); - jest.spyOn(ConnectionPropsForSessCfg as any, "loadSchemaForSessCfgProps").mockReturnValueOnce({ - port: { type: "number" } + jest.spyOn( + ConnectionPropsForSessCfg as any, + "loadSchemaForSessCfgProps" + ).mockReturnValueOnce({ + port: { type: "number" }, }); const initialSessCfg = { - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", _: [""], host: hostFromArgs, user: userFromArgs, - password: passFromArgs + password: passFromArgs, }; let theError; try { - await ConnectionPropsForSessCfg.addPropsOrPrompt(initialSessCfg, args); + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args + ); } catch (err) { theError = err; } @@ -1147,7 +1360,7 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(theError.message).toBe("Specified port was not a number."); }); - it("timeout waiting for user name", async() => { + it("timeout waiting for user name", async () => { const sleepReal = CliUtils.sleep; CliUtils.sleep = jest.fn(); const readPromptReal = CliUtils.readPrompt; @@ -1156,20 +1369,22 @@ describe("ConnectionPropsForSessCfg tests", () => { const initialSessCfg = { hostname: "SomeHost", port: 11, - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", _: [""], - password: "FakePassword" + password: "FakePassword", }; let sessCfgWithConnProps: ISession; let caughtError; try { - sessCfgWithConnProps = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args - ); + sessCfgWithConnProps = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args + ); } catch (thrownError) { caughtError = thrownError; } @@ -1179,7 +1394,7 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(caughtError.message).toBe("Timed out waiting for user."); }); - it("timeout waiting for password", async() => { + it("timeout waiting for password", async () => { const sleepReal = CliUtils.sleep; CliUtils.sleep = jest.fn(); const readPromptReal = CliUtils.readPrompt; @@ -1188,20 +1403,22 @@ describe("ConnectionPropsForSessCfg tests", () => { const initialSessCfg = { hostname: "SomeHost", port: 11, - rejectUnauthorized: true + rejectUnauthorized: true, }; const args = { $0: "zowe", _: [""], - user: "FakeUser" + user: "FakeUser", }; let sessCfgWithConnProps: ISession; let caughtError; try { - sessCfgWithConnProps = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args - ); + sessCfgWithConnProps = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args + ); } catch (thrownError) { caughtError = thrownError; } @@ -1211,7 +1428,7 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(caughtError.message).toBe("Timed out waiting for password."); }); - it("timeout waiting for host name", async() => { + it("timeout waiting for host name", async () => { const sleepReal = CliUtils.sleep; CliUtils.sleep = jest.fn(); const readPromptReal = CliUtils.readPrompt; @@ -1225,15 +1442,17 @@ describe("ConnectionPropsForSessCfg tests", () => { _: [""], port: 11, user: "FakeUser", - password: "FakePassword" + password: "FakePassword", }; let sessCfgWithConnProps: ISession; let caughtError; try { - sessCfgWithConnProps = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args - ); + sessCfgWithConnProps = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args + ); } catch (thrownError) { caughtError = thrownError; } @@ -1243,7 +1462,7 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(caughtError.message).toBe("Timed out waiting for hostname."); }); - it("timeout waiting for port number", async() => { + it("timeout waiting for port number", async () => { const sleepReal = CliUtils.sleep; CliUtils.sleep = jest.fn(); const readPromptReal = CliUtils.readPrompt; @@ -1257,15 +1476,17 @@ describe("ConnectionPropsForSessCfg tests", () => { _: [""], host: "SomeHost", user: "FakeUser", - password: "FakePassword" + password: "FakePassword", }; let sessCfgWithConnProps: ISession; let caughtError; try { - sessCfgWithConnProps = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args - ); + sessCfgWithConnProps = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args + ); } catch (thrownError) { caughtError = thrownError; } @@ -1277,7 +1498,8 @@ describe("ConnectionPropsForSessCfg tests", () => { it("should not log secure properties of session config", async () => { const mockLoggerDebug = jest.fn(); - const getImperativeLoggerSpy = jest.spyOn(Logger, "getImperativeLogger") + const getImperativeLoggerSpy = jest + .spyOn(Logger, "getImperativeLogger") .mockReturnValueOnce({ debug: mockLoggerDebug } as any); (ConnectionPropsForSessCfg as any).logSessCfg({ host: "SomeHost", @@ -1285,7 +1507,7 @@ describe("ConnectionPropsForSessCfg tests", () => { user: "FakeUser", password: "FakePassword", tokenType: SessConstants.TOKEN_TYPE_JWT, - tokenValue: "FakeToken" + tokenValue: "FakeToken", }); getImperativeLoggerSpy.mockRestore(); expect(mockLoggerDebug).toHaveBeenCalledTimes(1); @@ -1296,7 +1518,7 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(logOutput).not.toContain("FakeToken"); }); - it("SSO CallBack with getValuesBack", async() => { + it("SSO CallBack with getValuesBack", async () => { const initialSessCfg = { rejectUnauthorized: true, }; @@ -1305,28 +1527,28 @@ describe("ConnectionPropsForSessCfg tests", () => { port: 11, user: "FakeUser", password: "FakePassword", - rejectUnauthorized: false + rejectUnauthorized: false, }; const args = { $0: "zowe", - _: [""] + _: [""], }; const fakeFunction = jest.fn((neededProps) => { for (const value of neededProps) { switch (value) { - case "hostname" : + case "hostname": neededProps[value] = fakeFunctionSessCfg.hostname; break; - case "port" : + case "port": neededProps[value] = fakeFunctionSessCfg.port; break; - case "user" : + case "user": neededProps[value] = fakeFunctionSessCfg.user; break; - case "password" : + case "password": neededProps[value] = fakeFunctionSessCfg.password; break; - case "rejectUnauthorized" : + case "rejectUnauthorized": neededProps[value] = initialSessCfg.rejectUnauthorized; break; default: @@ -1335,9 +1557,12 @@ describe("ConnectionPropsForSessCfg tests", () => { } return neededProps; }); - const sessCfgWithConnProps = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, {getValuesBack: fakeFunction} - ); + const sessCfgWithConnProps = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { getValuesBack: fakeFunction } + ); expect(sessCfgWithConnProps.hostname).toBe("SomeHost"); expect(sessCfgWithConnProps.port).toBe(11); expect(sessCfgWithConnProps.user).toBe("FakeUser"); @@ -1349,7 +1574,7 @@ describe("ConnectionPropsForSessCfg tests", () => { expect(sessCfgWithConnProps.certKey).toBeUndefined(); }); - it("SSO CallBack with getValuesBack and partial session config", async() => { + it("SSO CallBack with getValuesBack and partial session config", async () => { const initialSessCfg = { password: "FakePassword", rejectUnauthorized: true, @@ -1366,19 +1591,19 @@ describe("ConnectionPropsForSessCfg tests", () => { const fakeFunction = jest.fn((neededProps) => { for (const value of neededProps) { switch (value) { - case "hostname" : + case "hostname": neededProps[value] = fakeFunctionSessCfg.hostname; break; - case "port" : + case "port": neededProps[value] = fakeFunctionSessCfg.port; break; - case "user" : + case "user": neededProps[value] = args.user; break; - case "password" : + case "password": neededProps[value] = initialSessCfg.password; break; - case "rejectUnauthorized" : + case "rejectUnauthorized": neededProps[value] = initialSessCfg.rejectUnauthorized; break; default: @@ -1387,9 +1612,12 @@ describe("ConnectionPropsForSessCfg tests", () => { } return neededProps; }); - const sessCfgWithConnProps = await ConnectionPropsForSessCfg.addPropsOrPrompt( - initialSessCfg, args, {getValuesBack: fakeFunction} - ); + const sessCfgWithConnProps = + await ConnectionPropsForSessCfg.addPropsOrPrompt( + initialSessCfg, + args, + { getValuesBack: fakeFunction } + ); expect(sessCfgWithConnProps.hostname).toBe("SomeHost"); expect(sessCfgWithConnProps.port).toBe(11); expect(sessCfgWithConnProps.user).toBe("FakeUser"); @@ -1464,4 +1692,135 @@ describe("ConnectionPropsForSessCfg tests", () => { ); expect((ConnectionPropsForSessCfg as any).secureSessCfgProps).toContain("keyPassphrase"); }); + describe("getValuesBack private function", () => { + // pretend that console.log works, but put data into a variable + let consoleMsgs = ""; + const connOpts: IOptionsForAddConnProps = { + parms: { + response: { + console: { + log: jest.fn((logArgs) => { + consoleMsgs += "\n" + logArgs; + }), + }, + }, + }, + } as any; + + let getValuesCallBack: any; + let clientPromptSpy: any; + + beforeEach(() => { + // establish a callback function with our fake console.log + getValuesCallBack = + ConnectionPropsForSessCfg["getValuesBack"](connOpts); + + // pretend that clientPrompt returns an answer + clientPromptSpy = jest + .spyOn(ConnectionPropsForSessCfg as any, "clientPrompt") + .mockResolvedValue(Promise.resolve("Some fake answer")); + // clear log messages from last test + consoleMsgs = ""; + }); + + afterEach(() => { + // restore original app implementations + clientPromptSpy.mockRestore(); + }); + + it("should state that you have no zowe config file", async () => { + // Pretend that we do not have a zowe config. + Object.defineProperty(ImperativeConfig.instance, "config", { + configurable: true, + get: jest.fn(() => { + return { + exists: false, + }; + }), + }); + + // call the function that we want to test + await getValuesCallBack(["hostname"]); + + expect(consoleMsgs).toContain( + "No Zowe client configuration exists." + ); + expect(consoleMsgs).toContain( + "Therefore, you will be asked for the" + ); + expect(consoleMsgs).toContain( + "connection properties that are required to complete your command." + ); + }); + + it("should state that V1 profiles are not supported", async () => { + // Pretend that we do not have a zowe config. + Object.defineProperty(ImperativeConfig.instance, "config", { + configurable: true, + get: jest.fn(() => { + return { + exists: false, + }; + }), + }); + + /* Pretend that we only have V1 profiles. + * onlyV1ProfilesExist is a getter property, so mock the property. + */ + Object.defineProperty(ConfigUtils, "onlyV1ProfilesExist", { + configurable: true, + get: jest.fn(() => { + return true; + }), + }); + + // call the function that we want to test + await getValuesCallBack(["hostname"]); + + expect(consoleMsgs).toContain( + "Only V1 profiles exist. V1 profiles are no longer supported. You should convert" + ); + expect(consoleMsgs).toContain( + "your V1 profiles to a newer Zowe client configuration. Therefore, you will be" + ); + expect(consoleMsgs).toContain( + "asked for the connection properties that are required to complete your command." + ); + }); + + it("should state that connection properties are missing from config", async () => { + // Pretend that we have a zowe config. + Object.defineProperty(ImperativeConfig.instance, "config", { + configurable: true, + get: jest.fn(() => { + return { + exists: true, + }; + }), + }); + + /* Pretend that we do not have any V1 profiles. + * onlyV1ProfilesExist is a getter property, so mock the property. + */ + Object.defineProperty(ConfigUtils, "onlyV1ProfilesExist", { + configurable: true, + get: jest.fn(() => { + return false; + }), + }); + + // call the function that we want to test + await getValuesCallBack(["hostname"]); + + expect(consoleMsgs).toContain( + "Some required connection properties have not been specified in your Zowe client" + ); + expect(consoleMsgs).toContain( + "configuration. Therefore, you will be asked for the connection properties that" + ); + expect(consoleMsgs).toContain( + "are required to complete your command." + ); + }); + }); }); diff --git a/packages/imperative/src/rest/index.ts b/packages/imperative/src/rest/index.ts index b8b059e42c..72ab85c224 100644 --- a/packages/imperative/src/rest/index.ts +++ b/packages/imperative/src/rest/index.ts @@ -17,12 +17,12 @@ export * from "./src/client/doc/IRestClientError"; export * from "./src/client/doc/IRestClientResponse"; export * from "./src/client/doc/IRestOptions"; export * from "./src/client/Headers"; -export * from "./src/client/Proxy"; +export * from "./src/client/ProxySettings"; export * from "./src/client/AbstractRestClient"; -export * from "./src/client/CompressionUtils"; +// export * from "./src/client/CompressionUtils"; export * from "./src/client/RestClient"; export * from "./src/client/RestConstants"; -export * from "./src/client/RestStandAloneUtils"; +// export * from "./src/client/RestStandAloneUtils"; export * from "./src/client/RestClientError"; export * as SessConstants from "./src/session/SessConstants"; diff --git a/packages/imperative/src/rest/src/client/AbstractRestClient.ts b/packages/imperative/src/rest/src/client/AbstractRestClient.ts index fa1e663d15..46b6eec4b3 100644 --- a/packages/imperative/src/rest/src/client/AbstractRestClient.ts +++ b/packages/imperative/src/rest/src/client/AbstractRestClient.ts @@ -29,11 +29,11 @@ import { RestClientError } from "./RestClientError"; import { Readable, Writable } from "stream"; import { IO } from "../../../io"; import { ITaskWithStatus, TaskProgress, TaskStage } from "../../../operations"; -import { NextVerFeatures, TextUtils } from "../../../utilities"; +import { TextUtils } from "../../../utilities"; import { IRestOptions } from "./doc/IRestOptions"; import * as SessConstants from "../session/SessConstants"; import { CompressionUtils } from "./CompressionUtils"; -import { Proxy } from "./Proxy"; +import { ProxySettings } from "./ProxySettings"; export type RestClientResolve = (data: string) => void; @@ -330,16 +330,8 @@ export abstract class AbstractRestClient { * Invoke any onError method whenever an error occurs on writing */ clientRequest.on("error", (errorResponse: any) => { - let errMsg: string; - // TODO:V3_ERR_FORMAT - Don't test for env variable in V3 - if (NextVerFeatures.useV3ErrFormat()) { - errMsg = "Failed to send an HTTP request."; - } else { // TODO:V3_ERR_FORMAT - Remove in V3 - errMsg = "http(s) request error event called"; - } - reject(this.populateError({ - msg: errMsg, + msg: "Failed to send an HTTP request.", causeErrors: errorResponse, source: "client" })); @@ -469,13 +461,13 @@ export abstract class AbstractRestClient { // NOTE(Kelosky): This cannot be set for http requests // options.agent = new https.Agent({secureProtocol: this.session.ISession.secureProtocol}); - const proxyUrl = Proxy.getSystemProxyUrl(this.session.ISession); + const proxyUrl = ProxySettings.getSystemProxyUrl(this.session.ISession); if (proxyUrl) { - if (Proxy.matchesNoProxySettings(this.session.ISession)) { + if (ProxySettings.matchesNoProxySettings(this.session.ISession)) { this.mLogger.info(`Proxy setting "${proxyUrl.href}" will not be used as hostname was found listed under "no_proxy" setting.`); } else { this.mLogger.info(`Using the following proxy setting for the request: ${proxyUrl.href}`); - options.agent = Proxy.getProxyAgent(this.session.ISession); + options.agent = ProxySettings.getProxyAgent(this.session.ISession); } } @@ -550,7 +542,7 @@ export abstract class AbstractRestClient { this.setTransferFlags(options.headers); const logResource = path.posix.join(path.posix.sep, - (this.session.ISession.basePath == null ? "" : this.session.ISession.basePath), resource); + this.session.ISession.basePath == null ? "" : this.session.ISession.basePath, resource); this.log.trace("Rest request: %s %s:%s%s %s", request, this.session.ISession.hostname, this.session.ISession.port, logResource, this.session.ISession.user ? "as user " + this.session.ISession.user : ""); @@ -605,7 +597,7 @@ export abstract class AbstractRestClient { { return false; } - if (! this.session.ISession.base64EncodedAuth && + if (!this.session.ISession.base64EncodedAuth && !(this.session.ISession.user && this.session.ISession.password)) { return false; @@ -614,7 +606,7 @@ export abstract class AbstractRestClient { this.log.trace("Using basic authentication"); const headerKeys: string[] = Object.keys(Headers.BASIC_AUTHORIZATION); const authentication: string = AbstractSession.BASIC_PREFIX + (this.session.ISession.base64EncodedAuth ?? - AbstractSession.getBase64Auth(this.session.ISession.user, this.session.ISession.password)); + AbstractSession.getBase64Auth(this.session.ISession.user, this.session.ISession.password)); headerKeys.forEach((property) => { restOptionsToSet.headers[property] = authentication; }); @@ -883,8 +875,8 @@ export abstract class AbstractRestClient { finalError.host = this.mSession.ISession.hostname; finalError.basePath = this.mSession.ISession.basePath; finalError.httpStatus = httpStatus; - finalError.errno = (nodeClientError != null) ? nodeClientError.errno : undefined; - finalError.syscall = (nodeClientError != null) ? nodeClientError.syscall : undefined; + finalError.errno = nodeClientError != null ? nodeClientError.errno : undefined; + finalError.syscall = nodeClientError != null ? nodeClientError.syscall : undefined; finalError.payload = this.mWriteData; finalError.headers = this.mReqHeaders; finalError.resource = this.mResource; @@ -897,41 +889,21 @@ export abstract class AbstractRestClient { `HTTP(S) client encountered an error. Request could not be initiated to host.\n` + `Review connection details (host, port) and ensure correctness.`; } else { - // TODO:V3_ERR_FORMAT - Don't test for env variable in V3 - if (NextVerFeatures.useV3ErrFormat()) { - detailMessage = - `Received HTTP(S) error ${finalError.httpStatus} = ${http.STATUS_CODES[finalError.httpStatus]}.`; - } else { // TODO:V3_ERR_FORMAT - Remove in V3 - detailMessage = - `HTTP(S) error status "${finalError.httpStatus}" received.\n` + - `Review request details (resource, base path, credentials, payload) and ensure correctness.`; - } + detailMessage = + `Received HTTP(S) error ${finalError.httpStatus} = ${http.STATUS_CODES[finalError.httpStatus]}.`; } - // TODO:V3_ERR_FORMAT - Don't test for env variable in V3 - if (NextVerFeatures.useV3ErrFormat()) { - detailMessage += "\n" + - "\nProtocol: " + finalError.protocol + - "\nHost: " + finalError.host + - "\nPort: " + finalError.port + - "\nBase Path: " + finalError.basePath + - "\nResource: " + finalError.resource + - "\nRequest: " + finalError.request + - "\nHeaders: " + headerDetails + - "\nPayload: " + payloadDetails + - "\nAuth type: " + this.mSession.ISession.type + - "\nAllow Unauth Cert: " + !this.mSession.ISession.rejectUnauthorized; - } else { // TODO:V3_ERR_FORMAT - Remove in V3 - detailMessage += "\n" + - "\nProtocol: " + finalError.protocol + - "\nHost: " + finalError.host + - "\nPort: " + finalError.port + - "\nBase Path: " + finalError.basePath + - "\nResource: " + finalError.resource + - "\nRequest: " + finalError.request + - "\nHeaders: " + headerDetails + - "\nPayload: " + payloadDetails; - } + detailMessage += "\n" + + "\nProtocol: " + finalError.protocol + + "\nHost: " + finalError.host + + "\nPort: " + finalError.port + + "\nBase Path: " + finalError.basePath + + "\nResource: " + finalError.resource + + "\nRequest: " + finalError.request + + "\nHeaders: " + headerDetails + + "\nPayload: " + payloadDetails + + "\nAuth type: " + this.mSession.ISession.type + + "\nAllow Unauth Cert: " + !this.mSession.ISession.rejectUnauthorized; finalError.additionalDetails = detailMessage; // Allow implementation to modify the error as necessary @@ -976,7 +948,7 @@ export abstract class AbstractRestClient { * @memberof AbstractRestClient */ private setTransferFlags(headers: http.OutgoingHttpHeaders) { - if ((headers[Headers.CONTENT_TYPE]) != null) { + if (headers[Headers.CONTENT_TYPE] != null) { const contentType = headers[Headers.CONTENT_TYPE]; if (contentType === Headers.APPLICATION_JSON[Headers.CONTENT_TYPE]) { this.mIsJson = true; @@ -996,8 +968,8 @@ export abstract class AbstractRestClient { if (this.response == null) { return false; } else { - return (this.response.statusCode >= RestConstants.HTTP_STATUS_200 && - this.response.statusCode < RestConstants.HTTP_STATUS_300); + return this.response.statusCode >= RestConstants.HTTP_STATUS_200 && + this.response.statusCode < RestConstants.HTTP_STATUS_300; } } diff --git a/packages/imperative/src/rest/src/client/Proxy.ts b/packages/imperative/src/rest/src/client/ProxySettings.ts similarity index 96% rename from packages/imperative/src/rest/src/client/Proxy.ts rename to packages/imperative/src/rest/src/client/ProxySettings.ts index 67ac9d685a..f535bc00d4 100644 --- a/packages/imperative/src/rest/src/client/Proxy.ts +++ b/packages/imperative/src/rest/src/client/ProxySettings.ts @@ -32,7 +32,7 @@ import { ISession } from '../session/doc/ISession'; * variables NO_PROXY or no_proxy. These work with a simple comma separated list of hostnames that need * to match with the hostname of the Zowe profile. */ -export class Proxy { +export class ProxySettings { /** * Retrieve an appropriate http.agent instance if proxy environment variables can be found. @@ -41,7 +41,7 @@ export class Proxy { * Uses the session's `rejectUnauthorized` also for the proxy connection. * @returns an instance of an appropriate subclass of node's https.agent if proxy * settings were found. Returns `undefined` if no proxy settings are found. - * @memberof Proxy + * @memberof ProxySettings */ public static getProxyAgent(session: ISession): Agent | undefined { const proxySetting = this.getProxySettings(session); @@ -60,7 +60,7 @@ export class Proxy { * @static * @param session Zowe `ISession` containing the hostname for the http request. * @returns `URL` to proxy server - * @memberof Proxy + * @memberof ProxySettings */ public static getSystemProxyUrl(session: ISession): URL | undefined { return this.getProxySettings(session)?.proxyUrl; @@ -75,7 +75,7 @@ export class Proxy { * @param session Zowe `ISession` containing the hostname for the http request. * @returns `true` if the Zowe session host matches an entry in the comma separated * list of hostnames in the environment variable. `false` otherwise. - * @memberof Proxy + * @memberof ProxySettings */ public static matchesNoProxySettings(session: ISession): boolean { const noProxyValues = this.getNoProxyEnvVariables(); @@ -94,7 +94,7 @@ export class Proxy { * @static * @param session Zowe `ISession` containing the hostname for the http request. * @returns instance of private `ProxySetting` or `undefined` - * @memberof Proxy + * @memberof ProxySettings */ private static getProxySettings(session: ISession): ProxySetting | undefined { if (this.matchesNoProxySettings(session)) { @@ -119,7 +119,7 @@ export class Proxy { * @private * @static * @returns `string` if valid variable is found or undefined. - * @memberof Proxy + * @memberof ProxySettings */ private static getHttpEnvVariables(): string | undefined { return env.HTTP_PROXY ?? env.http_proxy; @@ -130,7 +130,7 @@ export class Proxy { * @private * @static * @returns `string` if valid variable is found or undefined. - * @memberof Proxy + * @memberof ProxySettings */ private static getHttpsEnvVariables(): string | undefined { return env.HTTPS_PROXY ?? env.https_proxy ?? this.getHttpEnvVariables(); @@ -142,7 +142,7 @@ export class Proxy { * @static * @returns `string[]` of all hostnames found in the comma separated list * in lowercase without white spaces. - * @memberof Proxy + * @memberof ProxySettings */ private static getNoProxyEnvVariables(): string[] | undefined { const noProxyValue = env.NO_PROXY ?? env.no_proxy; diff --git a/packages/imperative/src/rest/src/client/RestClient.ts b/packages/imperative/src/rest/src/client/RestClient.ts index 6702ca9f4d..7ba3c7ab0a 100644 --- a/packages/imperative/src/rest/src/client/RestClient.ts +++ b/packages/imperative/src/rest/src/client/RestClient.ts @@ -501,7 +501,7 @@ export class RestClient extends AbstractRestClient { * @memberof RestClient */ public static hasQueryString(query: string): boolean { - return (query.slice(-1) !== RestConstants.QUERY_ID); + return query.slice(-1) !== RestConstants.QUERY_ID; } /** diff --git a/packages/imperative/src/rest/src/client/doc/IHeaderContent.ts b/packages/imperative/src/rest/src/client/doc/IHeaderContent.ts index 0a6d69dade..776e788566 100644 --- a/packages/imperative/src/rest/src/client/doc/IHeaderContent.ts +++ b/packages/imperative/src/rest/src/client/doc/IHeaderContent.ts @@ -9,6 +9,11 @@ * */ +/** + * Interface to add index signature to http headers + * @export + * @interface IHeaderContent + */ export interface IHeaderContent { [key: string]: string; } diff --git a/packages/imperative/src/rest/src/session/ConnectionPropsForSessCfg.ts b/packages/imperative/src/rest/src/session/ConnectionPropsForSessCfg.ts index d0a1a850c3..9f4dccbcbd 100644 --- a/packages/imperative/src/rest/src/session/ConnectionPropsForSessCfg.ts +++ b/packages/imperative/src/rest/src/session/ConnectionPropsForSessCfg.ts @@ -9,7 +9,7 @@ * */ -import { CliUtils, ImperativeConfig } from "../../../utilities"; +import { CliUtils, ImperativeConfig, TextUtils } from "../../../utilities"; import { ICommandArguments, IHandlerParameters } from "../../../cmd"; import { ImperativeError } from "../../../error"; import { IOptionsForAddConnProps } from "./doc/IOptionsForAddConnProps"; @@ -147,14 +147,16 @@ export class ConnectionPropsForSessCfg { if (ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.hostname) === false && !doNotPromptForValues.includes("hostname")) { promptForValues.push("hostname"); } - if (ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.port) === false && !doNotPromptForValues.includes("port")) { + + if ((ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.port) === false || sessCfgToUse.port === 0) && + !doNotPromptForValues.includes("port")) { promptForValues.push("port"); } const isTokenIrrelevant = ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.tokenValue) === false || - (connOpts.supportedAuthTypes && !connOpts.supportedAuthTypes.includes(SessConstants.AUTH_TYPE_TOKEN)); + connOpts.supportedAuthTypes && !connOpts.supportedAuthTypes.includes(SessConstants.AUTH_TYPE_TOKEN); const isCertIrrelevant = ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.cert) === false || - (connOpts.supportedAuthTypes && !connOpts.supportedAuthTypes.includes(SessConstants.AUTH_TYPE_CERT_PEM)); + connOpts.supportedAuthTypes && !connOpts.supportedAuthTypes.includes(SessConstants.AUTH_TYPE_CERT_PEM); if (isTokenIrrelevant && isCertIrrelevant) { if (ConnectionPropsForSessCfg.propHasValue(sessCfgToUse.user) === false && !doNotPromptForValues.includes("user")) { promptForValues.push("user"); @@ -191,6 +193,7 @@ export class ConnectionPropsForSessCfg { } } + // if (connOptsToUse.autoStore !== false && connOptsToUse.parms != null) { await ConfigAutoStore.storeSessCfgProps(connOptsToUse.parms, sessCfgToUse, promptForValues); } @@ -377,6 +380,30 @@ export class ConnectionPropsForSessCfg { private static getValuesBack(connOpts: IOptionsForAddConnProps): (properties: string[]) => Promise<{ [key: string]: any }> { return async (promptForValues: string[]) => { + /* The check for console.log in the following 'if' statement is only needed for tests + * which do not create a mock for the connOpts.parms.response.console.log property. + * In the real world, that property always exists for this CLI-only path of logic. + */ + if (promptForValues.length > 0 && connOpts?.parms?.response?.console?.log) { + // We need to prompt for some values. Determine why we need to prompt. + let reasonForPrompts: string = ""; + if (ImperativeConfig.instance.config?.exists) { + reasonForPrompts += "Some required connection properties have not been specified " + + "in your Zowe client configuration. "; + } else if (ConfigUtils.onlyV1ProfilesExist) { + reasonForPrompts += "Only V1 profiles exist. V1 profiles are no longer supported. " + + "You should convert your V1 profiles to a newer Zowe client configuration. "; + } else { + reasonForPrompts += "No Zowe client configuration exists. "; + } + + reasonForPrompts += "Therefore, you will be asked for the connection properties " + + "that are required to complete your command.\n"; + connOpts.parms.response.console.log(TextUtils.wordWrap( + TextUtils.chalk.yellowBright(reasonForPrompts)) + ); + } + const answers: { [key: string]: any } = {}; const profileSchema = this.loadSchemaForSessCfgProps(connOpts.parms, promptForValues); const serviceDescription = connOpts.serviceDescription || "your service"; diff --git a/packages/imperative/src/security/__tests__/CredentialManagerFactory.unit.test.ts b/packages/imperative/src/security/__tests__/CredentialManagerFactory.unit.test.ts index c98e9eaee4..008d094289 100644 --- a/packages/imperative/src/security/__tests__/CredentialManagerFactory.unit.test.ts +++ b/packages/imperative/src/security/__tests__/CredentialManagerFactory.unit.test.ts @@ -35,13 +35,13 @@ describe("CredentialManagerFactory", () => { it("should throw an error if no service name was provided", () => { expect(() => { CredentialManagerFactory.manager.initialize(); - }).toThrowError("Credential Manager not yet initialized!"); + }).toThrow("Credential Manager not yet initialized!"); }); it("should throw an error when getting the manager before init", () => { expect(() => { CredentialManagerFactory.manager.initialize(); - }).toThrowError("Credential Manager not yet initialized!"); + }).toThrow("Credential Manager not yet initialized!"); }); it("should throw an error when initialize is called twice", async () => { @@ -87,7 +87,7 @@ describe("CredentialManagerFactory", () => { expect(actualError.message).toContain(`${classFile} does not extend AbstractCredentialManager`); expect(() => { CredentialManagerFactory.manager.initialize(); - }).toThrowError("Credential Manager not yet initialized!"); + }).toThrow("Credential Manager not yet initialized!"); }); it("should handle a load failure", async () => { @@ -97,7 +97,7 @@ describe("CredentialManagerFactory", () => { expect(actualError.message).toContain(`Cannot find module '${classFile}'`); expect(() => { CredentialManagerFactory.manager.initialize(); - }).toThrowError("Credential Manager not yet initialized!"); + }).toThrow("Credential Manager not yet initialized!"); }); }); @@ -110,8 +110,8 @@ describe("CredentialManagerFactory", () => { beforeEach(async () => { // Generate a random name so we can verify that different names work - emulated.pluginName = generateRandomAlphaNumericString(Math.floor((Math.random() * nameMaxLength) + 1)); - emulated.cliName = generateRandomAlphaNumericString(Math.floor((Math.random() * nameMaxLength) + 1)); + emulated.pluginName = generateRandomAlphaNumericString(Math.floor(Math.random() * nameMaxLength + 1)); + emulated.cliName = generateRandomAlphaNumericString(Math.floor(Math.random() * nameMaxLength + 1)); }); afterEach(() => { @@ -167,7 +167,7 @@ describe("CredentialManagerFactory", () => { expect(actualError.message).toContain(`Cannot find module '${classFile}'`); expect(() => { CredentialManagerFactory.manager.initialize(); - }).toThrowError("Credential Manager not yet initialized!"); + }).toThrow("Credential Manager not yet initialized!"); }); it("should initialize a credential manager with a display name", async () => { diff --git a/packages/imperative/src/security/__tests__/CredentialManagerOverride.unit.test.ts b/packages/imperative/src/security/__tests__/CredentialManagerOverride.unit.test.ts index 2433cc66bb..dabac1d8f4 100644 --- a/packages/imperative/src/security/__tests__/CredentialManagerOverride.unit.test.ts +++ b/packages/imperative/src/security/__tests__/CredentialManagerOverride.unit.test.ts @@ -17,6 +17,8 @@ import { ICredentialManagerNameMap } from "../src/doc/ICredentialManagerNameMap" import { ImperativeConfig } from "../../utilities"; import { ImperativeError } from "../../error"; import { ISettingsFile } from "../../settings/src/doc/ISettingsFile"; +import { EventOperator, EventUtils } from "../../events"; + describe("CredentialManagerOverride", () => { let mockImpConfig: any; @@ -28,6 +30,8 @@ describe("CredentialManagerOverride", () => { cliHome: __dirname }; jest.spyOn(ImperativeConfig, "instance", "get").mockReturnValue(mockImpConfig); + jest.spyOn(EventUtils, "validateAppName").mockImplementation(jest.fn()); + jest.spyOn(EventOperator, "getZoweProcessor").mockReturnValue({emitZoweEvent: jest.fn()} as any); expectedSettings = { fileName: path.join(mockImpConfig.cliHome, "settings", "imperative.json"), @@ -53,13 +57,37 @@ describe("CredentialManagerOverride", () => { "credMgrDisplayName": "Secrets for Kubernetes", "credMgrPluginName": "@zowe/secrets-for-kubernetes-for-zowe-cli", "credMgrZEName": "Zowe.secrets-for-kubernetes" - } + }, + { + "credMgrDisplayName": false + }, ]; const receivedCredMgrs = CredentialManagerOverride.getKnownCredMgrs(); expect(receivedCredMgrs).toEqual(expectedCredMgrs); }); }); + describe("getCurrentCredMgr", () => { + it("should return the current credential manager", () => { + const getSettingsFileJsonSpy = jest.spyOn(CredentialManagerOverride as any, "getSettingsFileJson"); + getSettingsFileJsonSpy.mockReturnValue({json: {overrides: { CredentialManager: "test"}}}); + const current = CredentialManagerOverride.getCurrentCredMgr(); + expect(current).toEqual("test"); + }); + it("should return false if the credential management is disabled", () => { + const getSettingsFileJsonSpy = jest.spyOn(CredentialManagerOverride as any, "getSettingsFileJson"); + getSettingsFileJsonSpy.mockReturnValue({json: {overrides: { CredentialManager: false}}}); + const current = CredentialManagerOverride.getCurrentCredMgr(); + expect(current).toBe(false); + }); + it("should return the default credential manager if settings file does not exist", () => { + const getSettingsFileJsonSpy = jest.spyOn(CredentialManagerOverride as any, "getSettingsFileJson"); + getSettingsFileJsonSpy.mockImplementation(() => {throw "test";}); + const current = CredentialManagerOverride.getCurrentCredMgr(); + expect(current).toEqual(CredentialManagerOverride.DEFAULT_CRED_MGR_NAME); + }); + }); + describe("getCredMgrInfoByDisplayName", () => { it("should return null when name is not found", () => { const credMgrInfo = CredentialManagerOverride.getCredMgrInfoByDisplayName("NotACredMgrName"); diff --git a/packages/imperative/src/security/__tests__/DefaultCredentialManager.unit.test.ts b/packages/imperative/src/security/__tests__/DefaultCredentialManager.unit.test.ts index ca4ad370c7..90ccb040ab 100644 --- a/packages/imperative/src/security/__tests__/DefaultCredentialManager.unit.test.ts +++ b/packages/imperative/src/security/__tests__/DefaultCredentialManager.unit.test.ts @@ -11,7 +11,7 @@ jest.mock("@zowe/secrets-for-zowe-sdk"); -import * as path from "path"; +import { Module } from "module"; import { DefaultCredentialManager } from ".."; import { keyring as keytar } from "@zowe/secrets-for-zowe-sdk"; import { ImperativeError } from "../../error"; @@ -50,6 +50,9 @@ describe("DefaultCredentialManager", () => { }); describe("initialize", () => { + afterEach(() => { + jest.restoreAllMocks(); + }); it("should properly initialize keytar", async () => { await manager.initialize(); @@ -72,60 +75,22 @@ describe("DefaultCredentialManager", () => { expect(privateManager.loadError.message).toMatch(/^Failed to load Keytar module:/); }); - it("should look for keytar in CLI node_modules folder", async () => { - // Jest doesn't let us mock require.resolve, so instead we purposely - // fail the import and look for module path in the error message - const fakeCliPath = "/root/fakeCli"; - // eslint-disable-next-line deprecation/deprecation - const mainModule = process.mainModule; - // eslint-disable-next-line deprecation/deprecation - process.mainModule = { filename: fakeCliPath } as any; - const resolveSpy = jest.spyOn(path, "resolve").mockReturnValue(fakeCliPath); - - // Force enter the try catch - Object.defineProperty(manager, "keytar", { - writable: false - }); - - try { - await manager.initialize(); - - expect(privateManager.keytar).toBeUndefined(); - expect(privateManager.loadError).toBeInstanceOf(ImperativeError); - const error: Error = privateManager.loadError.causeErrors; - expect(error).toBeDefined(); - expect(error.message).toContain("Cannot resolve module"); - expect(error.message).toContain(fakeCliPath); - } finally { - // eslint-disable-next-line deprecation/deprecation - process.mainModule = mainModule; - resolveSpy.mockRestore(); - } - }); - it("should look for keytar in local node_modules folder", async () => { - // eslint-disable-next-line deprecation/deprecation - const mainModule = process.mainModule; - // eslint-disable-next-line deprecation/deprecation - process.mainModule = { filename: "/root/fakeCli" } as any; + const mainModule = require.main; + jest.spyOn(Module.prototype, "require").mockReturnValue({...require, main: {...mainModule, filename: "/root/fakeCli"} as any} as any); // Force enter the try catch Object.defineProperty(manager, "keytar", { writable: false }); - try { - await manager.initialize(); - - expect(privateManager.keytar).toBeUndefined(); - expect(privateManager.loadError).toBeInstanceOf(ImperativeError); - const error: Error = privateManager.loadError.causeErrors; - expect(error).toBeDefined(); - expect(error.message).toContain("Cannot assign to read only property"); - } finally { - // eslint-disable-next-line deprecation/deprecation - process.mainModule = mainModule; - } + await manager.initialize(); + + expect(privateManager.keytar).toBeUndefined(); + expect(privateManager.loadError).toBeInstanceOf(ImperativeError); + const error: Error = privateManager.loadError.causeErrors; + expect(error).toBeDefined(); + expect(error.message).toContain("Cannot assign to read only property"); }); }); @@ -168,7 +133,7 @@ describe("DefaultCredentialManager", () => { expect(() => { privateManager.checkForKeytar(); - }).toThrowError(privateManager.loadError); + }).toThrow(privateManager.loadError); }); it("should throw an error if keytar and load error are missing", () => { privateManager.keytar = null; @@ -176,7 +141,7 @@ describe("DefaultCredentialManager", () => { expect(() => { privateManager.checkForKeytar(); - }).toThrowError(ImperativeError); + }).toThrow(ImperativeError); }); }); diff --git a/packages/imperative/src/security/__tests__/doc/ICredentialManagerNameMap.unit.test.ts b/packages/imperative/src/security/__tests__/doc/ICredentialManagerNameMap.unit.test.ts index a900552d89..617cb8c888 100644 --- a/packages/imperative/src/security/__tests__/doc/ICredentialManagerNameMap.unit.test.ts +++ b/packages/imperative/src/security/__tests__/doc/ICredentialManagerNameMap.unit.test.ts @@ -18,7 +18,7 @@ describe("ICredentialManagerNameMap", () => { join(__dirname, "../../src/doc/ICredentialManagerNameMap.ts"), "utf8" ); - expect(nameMap).toContain("credMgrDisplayName: string;"); + expect(nameMap).toContain("credMgrDisplayName: string | false;"); expect(nameMap).toContain("credMgrPluginName?: string;"); expect(nameMap).toContain("credMgrZEName?: string;"); }); diff --git a/packages/imperative/src/security/src/CredentialManagerFactory.ts b/packages/imperative/src/security/src/CredentialManagerFactory.ts index 011d804068..90134a1f46 100644 --- a/packages/imperative/src/security/src/CredentialManagerFactory.ts +++ b/packages/imperative/src/security/src/CredentialManagerFactory.ts @@ -82,13 +82,13 @@ export class CredentialManagerFactory { } // If the display name is not passed, use the cli name - const displayName = (params.displayName == null) ? params.service : params.displayName; + const displayName = params.displayName ?? params.service; // If a manager override was not passed, use the default keytar manager - const Manager = (params.Manager == null) ? DefaultCredentialManager : params.Manager; + const Manager = params.Manager ?? DefaultCredentialManager; // Default invalid on failure to false if not specified - params.invalidOnFailure = (params.invalidOnFailure == null) ? false : params.invalidOnFailure; + params.invalidOnFailure ??= false; if (this.mManager != null) { // Something tried to change the already existing credential manager, we should stop this. @@ -117,7 +117,7 @@ export class CredentialManagerFactory { if (manager instanceof AbstractCredentialManager) { this.mManager = manager; } else { - const message = (typeof Manager === "string") ? + const message = typeof Manager === "string" ? `The manager provided at ${Manager} does not extend AbstractCredentialManager properly!` : "A bad object was provided to the CredentialManagerFactory.initialize() method. This could be " + "due to a bad plugin."; diff --git a/packages/imperative/src/security/src/CredentialManagerOverride.ts b/packages/imperative/src/security/src/CredentialManagerOverride.ts index 60459512be..261c063fbc 100644 --- a/packages/imperative/src/security/src/CredentialManagerOverride.ts +++ b/packages/imperative/src/security/src/CredentialManagerOverride.ts @@ -16,6 +16,8 @@ import { ICredentialManagerNameMap } from "./doc/ICredentialManagerNameMap"; import { ImperativeConfig } from "../../utilities"; import { ImperativeError } from "../../error"; import { ISettingsFile } from "../../settings/src/doc/ISettingsFile"; +import { ZoweSharedEvents } from "../../events"; +import { EventOperator } from "../../events/src/EventOperator"; /** * This class provides access to the known set of credential manager overrides @@ -38,7 +40,10 @@ export class CredentialManagerOverride { "credMgrDisplayName": "Secrets for Kubernetes", "credMgrPluginName": "@zowe/secrets-for-kubernetes-for-zowe-cli", "credMgrZEName": "Zowe.secrets-for-kubernetes" - } + }, + { + "credMgrDisplayName": false + }, ]; //________________________________________________________________________ @@ -51,7 +56,7 @@ export class CredentialManagerOverride { * @returns An ICredentialManagerNameMap or * null if the specified plugin is not a known credential manager. */ - public static getCredMgrInfoByDisplayName(credMgrDisplayName: string) : ICredentialManagerNameMap | null { + public static getCredMgrInfoByDisplayName(credMgrDisplayName: string | false) : ICredentialManagerNameMap | null { return this.KNOWN_CRED_MGRS.find((credMgr) => credMgr.credMgrDisplayName === credMgrDisplayName) ?? null; } @@ -91,6 +96,21 @@ export class CredentialManagerOverride { return this.KNOWN_CRED_MGRS; } + //________________________________________________________________________ + /** + * Get the active credential manager. + * + * @returns Information about the current redential managers or false if none is set. + */ + public static getCurrentCredMgr() : string | false { + try { + const settings = this.getSettingsFileJson(); + return settings.json.overrides.CredentialManager; + } catch (err) { + return this.DEFAULT_CRED_MGR_NAME; + } + } + /** * Record the specified credential manager in the configuration of overrides. * A plugin or ZE extension that provides a credential manager would record @@ -101,7 +121,7 @@ export class CredentialManagerOverride { * * @throws An ImperativeError upon error. */ - public static recordCredMgrInConfig(newCredMgrName: string) : void { + public static recordCredMgrInConfig(newCredMgrName: string | false) : void { const credMgrInfo: ICredentialManagerNameMap = CredentialManagerOverride.getCredMgrInfoByDisplayName(newCredMgrName); if (credMgrInfo === null) { @@ -132,6 +152,7 @@ export class CredentialManagerOverride { settings.json.overrides.CredentialManager = newCredMgrName; try { writeJsonSync(settings.fileName, settings.json, {spaces: 2}); + EventOperator.getZoweProcessor().emitZoweEvent(ZoweSharedEvents.ON_CREDENTIAL_MANAGER_CHANGED); } catch (error) { throw new ImperativeError({ msg: "Unable to write settings file = " + settings.fileName + @@ -157,7 +178,7 @@ export class CredentialManagerOverride { * * @throws An ImperativeError upon error. */ - public static recordDefaultCredMgrInConfig(credMgrToReplace: string) : void { + public static recordDefaultCredMgrInConfig(credMgrToReplace: string | false) : void { // read in the existing settings file let settings: any; try { @@ -186,6 +207,7 @@ export class CredentialManagerOverride { settings.json.overrides.CredentialManager = this.DEFAULT_CRED_MGR_NAME; try { writeJsonSync(settings.fileName, settings.json, {spaces: 2}); + EventOperator.getZoweProcessor().emitZoweEvent(ZoweSharedEvents.ON_CREDENTIAL_MANAGER_CHANGED); } catch (error) { throw new ImperativeError({ msg: "Unable to write settings file = " + settings.fileName + @@ -219,7 +241,7 @@ export class CredentialManagerOverride { "\nReason: " + error.message }); } - if ( typeof(settings.json?.overrides?.CredentialManager) === "undefined") { + if ( typeof settings.json?.overrides?.CredentialManager === "undefined") { throw new ImperativeError({ msg: "The property key 'overrides.CredentialManager' does not exist in settings file = " + settings.fileName diff --git a/packages/imperative/src/security/src/DefaultCredentialManager.ts b/packages/imperative/src/security/src/DefaultCredentialManager.ts index 3d2e511c32..a89669c448 100644 --- a/packages/imperative/src/security/src/DefaultCredentialManager.ts +++ b/packages/imperative/src/security/src/DefaultCredentialManager.ts @@ -116,14 +116,12 @@ export class DefaultCredentialManager extends AbstractCredentialManager { */ public async initialize(): Promise { try { - // Imperative overrides the value of process.mainModule.filename to point to + // Imperative overrides the value of require.main.filename to point to // our calling CLI. Since our caller must supply keytar, we search for keytar // within our caller's path. const requireOpts: any = {}; - // eslint-disable-next-line deprecation/deprecation - if (process.mainModule?.filename != null) { - // eslint-disable-next-line deprecation/deprecation - requireOpts.paths = [process.mainModule.filename, ...require.resolve.paths("@zowe/secrets-for-zowe-sdk")]; + if (require.main.filename != null) { + requireOpts.paths = [require.main.filename, ...require.resolve.paths("@zowe/secrets-for-zowe-sdk")]; } // use helper function for require.resolve so it can be mocked in jest tests const keytarPath = require.resolve("@zowe/secrets-for-zowe-sdk", requireOpts); diff --git a/packages/imperative/src/security/src/abstract/AbstractCredentialManager.ts b/packages/imperative/src/security/src/abstract/AbstractCredentialManager.ts index e647e61f9e..c5fae99f43 100644 --- a/packages/imperative/src/security/src/abstract/AbstractCredentialManager.ts +++ b/packages/imperative/src/security/src/abstract/AbstractCredentialManager.ts @@ -9,8 +9,8 @@ * */ +/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ import { ImperativeError } from "../../../error"; - /** * String credential */ diff --git a/packages/imperative/src/security/src/doc/ICredentialManagerNameMap.ts b/packages/imperative/src/security/src/doc/ICredentialManagerNameMap.ts index 57b38e8e27..2a7e88a456 100644 --- a/packages/imperative/src/security/src/doc/ICredentialManagerNameMap.ts +++ b/packages/imperative/src/security/src/doc/ICredentialManagerNameMap.ts @@ -24,8 +24,11 @@ export interface ICredentialManagerNameMap { /** * Name of the credential manager. This is the name that will be stored in * $ZOWE_CLI_HOME/settings/imperative.json. + * + * A boolean value of false will be accepted. + * This indicates that credentials may be stored in plain text. */ - credMgrDisplayName: string; + credMgrDisplayName: string | false; /** * Name of the plugin that supplies the credential manager override software. diff --git a/packages/imperative/src/utilities/__tests__/CliUtils.unit.test.ts b/packages/imperative/src/utilities/__tests__/CliUtils.unit.test.ts index 3dcc16840d..b107ed6cd3 100644 --- a/packages/imperative/src/utilities/__tests__/CliUtils.unit.test.ts +++ b/packages/imperative/src/utilities/__tests__/CliUtils.unit.test.ts @@ -11,12 +11,9 @@ import * as stream from "stream"; import { CliUtils } from "../src/CliUtils"; -import { CommandProfiles, ICommandOptionDefinition } from "../../cmd"; -import { IProfile } from "../../profiles"; +import { ICommandOptionDefinition } from "../../cmd"; import { ImperativeError } from "../../error"; -import * as prompt from "readline-sync"; - -jest.mock("readline-sync"); +import { Config, IConfig } from "../../config"; const TEST_PREFIX = "TEST_CLI_PREFIX"; const boolEnv = TEST_PREFIX + "_OPT_FAKE_BOOL_OPT"; @@ -25,6 +22,31 @@ const stringAliasEnv = TEST_PREFIX + "_OPT_FAKE_STRING_OPT_WITH_ALIASES"; const numberEnv = TEST_PREFIX + "_OPT_FAKE_NUMBER_OPT"; const arrayEnv = TEST_PREFIX + "_OPT_FAKE_ARRAY_OPT"; +function mockConfigApi(properties: IConfig | undefined): any { + properties = properties || Config.empty(); + return { + api: { + layers: { + get: () => ({ + exists: true, + path: "fakePath", + properties + }) + }, + profiles: { + defaultGet: jest.fn().mockReturnValue(properties.profiles[properties.defaults.banana]?.properties), + exists: () => properties.defaults.banana != null, + getProfilePathFromName: (name: string) => `profiles.${name}` + }, + secure: { + securePropsForProfile: jest.fn().mockReturnValue([]) + } + }, + exists: true, + properties + }; +} + describe("CliUtils", () => { describe("extractEnvForOptions", () => { @@ -125,18 +147,6 @@ describe("CliUtils", () => { }); }); - describe("promptForInput", () => { - it("should return the mocked value", () => { - const mockedPromptValue = "My value is here "; - (prompt as any).question = jest.fn(() => { - return mockedPromptValue; - }); - // eslint-disable-next-line deprecation/deprecation - const value = CliUtils.promptForInput("my message goes here:"); - expect(value).toEqual(mockedPromptValue); - }); - }); - describe("sleep", () => { it("should sleep for 1 second", async () => { const startTime = Date.now(); @@ -148,78 +158,6 @@ describe("CliUtils", () => { }); }); - describe("promptWithTimeout", () => { - let readline = require("readline"); - let readlineReal: any; - const mockedAnswer = "User answer"; - - beforeEach(() => { - readlineReal = readline; - readline.createInterface = jest.fn(() => { - return { - prompt: jest.fn(() => { - // do nothing - }), - on: jest.fn((eventName: string, callback: any) => { - if (eventName === "line") { - callback(mockedAnswer); - } - return { - on: jest.fn((chainedEvtNm: string, chainedCallBack: any) => { - if (chainedEvtNm === "close") { - chainedCallBack(); - } - }), - }; - }), - output: { - write: jest.fn(() => { - // do nothing - }) - }, - close: jest.fn(() => { - // do nothing - }) - }; - }); - }); - - afterEach(() => { - readline = readlineReal; - }); - - it("should return the user's answer", async () => { - // eslint-disable-next-line deprecation/deprecation - const answer = await CliUtils.promptWithTimeout("Question to be asked: "); - expect(answer).toEqual(mockedAnswer); - }); - - it("should accept a hideText parameter", async () => { - // eslint-disable-next-line deprecation/deprecation - const answer = await CliUtils.promptWithTimeout("Should we hide your answer: ", true); - expect(answer).toEqual(mockedAnswer); - }); - - it("should accept a secToWait parameter", async () => { - const secToWait = 15; - // eslint-disable-next-line deprecation/deprecation - const answer = await CliUtils.promptWithTimeout("Should wait your amount of time: ", - false, secToWait - ); - expect(answer).toEqual(mockedAnswer); - }); - - it("should limit to a max secToWait", async () => { - const tooLong = 1000; - // eslint-disable-next-line deprecation/deprecation - const answer = await CliUtils.promptWithTimeout("Should wait your amount of time: ", - false, tooLong - ); - expect(answer).toEqual(mockedAnswer); - }); - - }); - describe("readPrompt", () => { const readline = require("readline"); const oldCreateInterface = readline.createInterface; @@ -248,14 +186,15 @@ describe("CliUtils", () => { it("should accept a secToWait parameter", async () => { const secToWait = 15; const answer = await CliUtils.readPrompt("Should wait your amount of time: ", - { hideText: false, secToWait } + { hideText: false, secToWait: secToWait } ); expect(answer).toEqual(mockedAnswer); }); it("should limit to a max secToWait", async () => { const tooLong = 1000; - const answer = await CliUtils.readPrompt("Should wait your amount of time: ", + const answer = await CliUtils.readPrompt( + "Should wait your amount of time: ", { hideText: false, secToWait: tooLong } ); expect(answer).toEqual(mockedAnswer); @@ -294,7 +233,7 @@ describe("CliUtils", () => { it("should produce a deprecated message when deprecated", () => { responseErrText = notSetYet; CliUtils.showMsgWhenDeprecated(handlerParms); - expect(responseErrText).toEqual("Recommended replacement: " + + expect(responseErrText).toContain("Recommended replacement: " + handlerParms.definition.deprecatedReplacement); }); @@ -302,7 +241,7 @@ describe("CliUtils", () => { responseErrText = notSetYet; handlerParms.positionals = ["positional_one"]; CliUtils.showMsgWhenDeprecated(handlerParms); - expect(responseErrText).toEqual("Recommended replacement: " + + expect(responseErrText).toContain("Recommended replacement: " + handlerParms.definition.deprecatedReplacement); }); @@ -310,7 +249,7 @@ describe("CliUtils", () => { responseErrText = notSetYet; handlerParms.positionals = []; CliUtils.showMsgWhenDeprecated(handlerParms); - expect(responseErrText).toEqual("Recommended replacement: " + + expect(responseErrText).toContain("Recommended replacement: " + handlerParms.definition.deprecatedReplacement); expect(responseErrText).not.toContain("Obsolete component. No replacement exists"); }); @@ -348,7 +287,7 @@ describe("CliUtils", () => { }); }); - describe("getOptValueFromProfiles", () => { + describe("getOptValuesFromConfig", () => { const FAKE_OPTS: ICommandOptionDefinition[] = [{ name: "fake-string-opt", @@ -379,10 +318,8 @@ describe("CliUtils", () => { it("should throw an imperative error if a required profile is not present", () => { let error; try { - const args = CliUtils.getOptValueFromProfiles( - new CommandProfiles(new Map()), - { required: ["banana"] }, - FAKE_OPTS); + CliUtils.getOptValuesFromConfig(mockConfigApi(undefined), + { required: ["banana"] } as any, {} as any, FAKE_OPTS); } catch (e) { error = e; } @@ -392,106 +329,129 @@ describe("CliUtils", () => { }); it("should return nothing if a profile was optional and not loaded", () => { - const args = CliUtils.getOptValueFromProfiles( - new CommandProfiles(new Map()), - { optional: ["banana"] }, - FAKE_OPTS); + const args = CliUtils.getOptValuesFromConfig(mockConfigApi(undefined), + { optional: ["banana"] }, {} as any, FAKE_OPTS); expect(Object.keys(args).length).toBe(0); }); it("should return args (from definitions with no hyphen in name) extracted from loaded profile", () => { - const map = new Map(); - map.set("banana", [{ type: "banana", name: "fakebanana", nohyphen: "specified in profile" }]); - const args = CliUtils.getOptValueFromProfiles( - new CommandProfiles(map), - { optional: ["banana"] }, - FAKE_OPTS); + const args = CliUtils.getOptValuesFromConfig( + mockConfigApi({ + profiles: { + fakebanana: { + type: "banana", + properties: { + nohyphen: "specified in profile" + } + } + }, + defaults: { banana: "fakebanana" } + }), + { optional: ["banana"] }, {} as any, FAKE_OPTS); expect(args).toMatchSnapshot(); }); it("should return args (with both cases) extracted from loaded profile, preferring the camel case", () => { - const map = new Map(); - map.set("banana", [{ - "type": "banana", - "name": "fakebanana", - "couldBeEither": "should be me", - "could-be-either": "should not be me" - }]); - const args = CliUtils.getOptValueFromProfiles( - new CommandProfiles(map), - { optional: ["banana"] }, - FAKE_OPTS); + const args = CliUtils.getOptValuesFromConfig( + mockConfigApi({ + profiles: { + fakebanana: { + type: "banana", + properties: { + couldBeEither: "should be me", + "could-be-either": "should not be me" + } + } + }, + defaults: { banana: "fakebanana" } + }), + { optional: ["banana"] }, {} as any, FAKE_OPTS); expect(args).toMatchSnapshot(); }); it("should return args (with both cases) extracted from loaded profile, preferring the kebab case", () => { - const map = new Map(); - map.set("banana", [{ - "type": "banana", - "name": "fakebanana", - "fakeStringOpt": "should not be me", - "fake-string-opt": "should be me" - }]); - const args = CliUtils.getOptValueFromProfiles( - new CommandProfiles(map), - { optional: ["banana"] }, - FAKE_OPTS); + const args = CliUtils.getOptValuesFromConfig( + mockConfigApi({ + profiles: { + fakebanana: { + type: "banana", + properties: { + fakeStringOpt: "should not be me", + "fake-string-opt": "should be me" + } + } + }, + defaults: { banana: "fakebanana" } + }), + { optional: ["banana"] }, {} as any, FAKE_OPTS); expect(args).toMatchSnapshot(); }); it("should return args with both cases, if the option is camel and the profile is kebab", () => { - const map = new Map(); - map.set("banana", [{ - "type": "banana", - "name": "fakebanana", - "could-be-either": "should be me" - }]); - const args = CliUtils.getOptValueFromProfiles( - new CommandProfiles(map), - { optional: ["banana"] }, - FAKE_OPTS); + const args = CliUtils.getOptValuesFromConfig( + mockConfigApi({ + profiles: { + fakebanana: { + type: "banana", + properties: { + "could-be-either": "should be me" + } + } + }, + defaults: { banana: "fakebanana" } + }), + { optional: ["banana"] }, {} as any, FAKE_OPTS); expect(args).toMatchSnapshot(); }); it("should return args with both cases, if the option is kebab and the profile is camel", () => { - const map = new Map(); - map.set("banana", [{ - type: "banana", - name: "fakebanana", - fakeStringOpt: "should be me" - }]); - const args = CliUtils.getOptValueFromProfiles( - new CommandProfiles(map), - { optional: ["banana"] }, - FAKE_OPTS); + const args = CliUtils.getOptValuesFromConfig( + mockConfigApi({ + profiles: { + fakebanana: { + type: "banana", + properties: { + fakeStringOpt: "should be me" + } + } + }, + defaults: { banana: "fakebanana" } + }), + { optional: ["banana"] }, {} as any, FAKE_OPTS); expect(args).toMatchSnapshot(); }); it("should return args with aliases if extracted option from a profile", () => { - const map = new Map(); - map.set("banana", [{ - type: "banana", - name: "fakebanana", - withAlias: "should have 'w' on args object too" - }]); - const args = CliUtils.getOptValueFromProfiles( - new CommandProfiles(map), - { optional: ["banana"] }, - FAKE_OPTS); + const args = CliUtils.getOptValuesFromConfig( + mockConfigApi({ + profiles: { + fakebanana: { + type: "banana", + properties: { + withAlias: "should have 'w' on args object too" + } + } + }, + defaults: { banana: "fakebanana" } + }), + { optional: ["banana"] }, {} as any, FAKE_OPTS); expect(args).toMatchSnapshot(); }); it("should return args if extracted option from a profile is only available as an alias", () => { - const map = new Map(); - map.set("banana", [{ - type: "banana", - name: "fakebanana", - username: "fake" - }]); - const args = CliUtils.getOptValueFromProfiles( - new CommandProfiles(map), - { optional: ["banana"] }, - FAKE_OPTS); + const args = CliUtils.getOptValuesFromConfig( + mockConfigApi({ + profiles: { + fakebanana: { + type: "banana", + properties: { + username: "fake" + } + } + }, + defaults: { banana: "fakebanana" } + }), + { optional: ["banana"] }, {} as any, FAKE_OPTS); expect(args).toEqual({ user: "fake", username: "fake" }); }); }); diff --git a/packages/imperative/src/utilities/__tests__/NextVerFeatures.unit.test.ts b/packages/imperative/src/utilities/__tests__/NextVerFeatures.unit.test.ts deleted file mode 100644 index 9406008fdd..0000000000 --- a/packages/imperative/src/utilities/__tests__/NextVerFeatures.unit.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { ImperativeConfig } from "../src/ImperativeConfig"; -import { NextVerFeatures } from "../src/NextVerFeatures"; - -describe("NextVerFeatures", () => { - const impCfg: ImperativeConfig = ImperativeConfig.instance; - - beforeAll(() => { - // impCfg.getCliCmdName is a getter of a property, so mock the property - Object.defineProperty(impCfg, "envVariablePrefix", { - configurable: true, - get: jest.fn(() => { - return "ZOWE"; - }) - }); - }); - - describe("useV3ErrFormat", () => { - - it("should return false when environment variable is not set", () => { - delete process.env.ZOWE_V3_ERR_FORMAT; - expect(NextVerFeatures.useV3ErrFormat()).toBe(false); - }); - - it("should return true when environment variable is set to lowercase true", () => { - process.env.ZOWE_V3_ERR_FORMAT = "true"; - expect(NextVerFeatures.useV3ErrFormat()).toBe(true); - }); - - it("should return true when environment variable is set to uppercase TRUE", () => { - process.env.ZOWE_V3_ERR_FORMAT = "TRUE"; - expect(NextVerFeatures.useV3ErrFormat()).toBe(true); - }); - - it("should return false when environment variable is set to a non-true value", () => { - process.env.ZOWE_V3_ERR_FORMAT = "someGoofyValue"; - expect(NextVerFeatures.useV3ErrFormat()).toBe(false); - }); - }); -}); diff --git a/packages/imperative/src/utilities/__tests__/ProcessUtils.unit.test.ts b/packages/imperative/src/utilities/__tests__/ProcessUtils.unit.test.ts index 3db03339f4..9e5000466c 100644 --- a/packages/imperative/src/utilities/__tests__/ProcessUtils.unit.test.ts +++ b/packages/imperative/src/utilities/__tests__/ProcessUtils.unit.test.ts @@ -10,7 +10,7 @@ */ import * as spawn from "cross-spawn"; -import { ExecUtils, GuiResult, ImperativeConfig, ProcessUtils } from "../../utilities"; +import { GuiResult, ImperativeConfig, ProcessUtils } from "../../utilities"; jest.mock("cross-spawn"); jest.mock("opener"); @@ -240,11 +240,6 @@ describe("ProcessUtils tests", () => { describe("openInEditor", () => { it("should open file in graphical editor", async () => { jest.spyOn(ProcessUtils, "isGuiAvailable").mockReturnValueOnce(GuiResult.GUI_AVAILABLE); - jest.spyOn(ImperativeConfig, "instance", "get").mockReturnValue({ - loadedConfig: { - envVariablePrefix: "TEST_CLI" - } - } as any); const mockOpener = require("opener"); await ProcessUtils.openInEditor("filePath"); expect(mockOpener).toHaveBeenCalledWith("filePath"); @@ -252,34 +247,14 @@ describe("ProcessUtils tests", () => { it("should open file in custom graphical editor", async () => { jest.spyOn(ProcessUtils, "isGuiAvailable").mockReturnValueOnce(GuiResult.GUI_AVAILABLE); - jest.spyOn(ImperativeConfig, "instance", "get").mockReturnValue({ - loadedConfig: { - envVariablePrefix: "TEST_CLI" - } - } as any); const mockOpener = require("opener"); - try { - process.env.TEST_CLI_EDITOR = "fakeEdit"; - await ProcessUtils.openInEditor("filePath"); - } finally { - delete process.env.TEST_CLI_EDITOR; - } + await ProcessUtils.openInEditor("filePath", "fakeEdit"); expect(spawn.spawn).toHaveBeenCalledWith("fakeEdit", ["filePath"], { stdio: "inherit" }); }); it("should open file in custom command-line editor", async () => { jest.spyOn(ProcessUtils, "isGuiAvailable").mockReturnValueOnce(GuiResult.NO_GUI_NO_DISPLAY); - jest.spyOn(ImperativeConfig, "instance", "get").mockReturnValue({ - loadedConfig: { - envVariablePrefix: "TEST_CLI" - } - } as any); - try { - process.env.TEST_CLI_EDITOR = "fakeEdit"; - await ProcessUtils.openInEditor("filePath"); - } finally { - delete process.env.TEST_CLI_EDITOR; - } + await ProcessUtils.openInEditor("filePath", "fakeEdit"); expect(spawn.spawn).toHaveBeenCalledWith("fakeEdit", ["filePath"], { stdio: "inherit" }); }); @@ -292,22 +267,4 @@ describe("ProcessUtils tests", () => { expect(spawn.spawn).toHaveBeenCalledWith("vi", ["filePath"], { stdio: "inherit" }); }); }); - - // TODO: Remove this entire 'describe' section in V3 when the @deprecated execAndCheckOutput function is removed - describe("execAndCheckOutput", () => { - afterEach(() => { - jest.clearAllMocks(); - }); - - it("should just pass through to ExecUtils.spawnAndGetOutput", () => { - const message = "Hello world!"; - const options: any = { cwd: __dirname }; - const stdoutBuffer = Buffer.from(message + "\n"); - const spawnSpy = jest.spyOn(ExecUtils, "spawnAndGetOutput").mockReturnValueOnce(stdoutBuffer as any); - // eslint-disable-next-line deprecation/deprecation - const execOutput = ProcessUtils.execAndCheckOutput("echo", [message], options); - expect(spawnSpy).toHaveBeenCalledWith("echo", [message], options); - expect(execOutput).toBe(stdoutBuffer); - }); - }); }); \ No newline at end of file diff --git a/packages/imperative/src/utilities/__tests__/__snapshots__/CliUtils.unit.test.ts.snap b/packages/imperative/src/utilities/__tests__/__snapshots__/CliUtils.unit.test.ts.snap index 38efab29ef..c804cc3384 100644 --- a/packages/imperative/src/utilities/__tests__/__snapshots__/CliUtils.unit.test.ts.snap +++ b/packages/imperative/src/utilities/__tests__/__snapshots__/CliUtils.unit.test.ts.snap @@ -98,27 +98,27 @@ Object { } `; -exports[`CliUtils getOptValueFromProfiles should return args (from definitions with no hyphen in name) extracted from loaded profile 1`] = ` +exports[`CliUtils getOptValuesFromConfig should return args (from definitions with no hyphen in name) extracted from loaded profile 1`] = ` Object { "nohyphen": "specified in profile", } `; -exports[`CliUtils getOptValueFromProfiles should return args (with both cases) extracted from loaded profile, preferring the camel case 1`] = ` +exports[`CliUtils getOptValuesFromConfig should return args (with both cases) extracted from loaded profile, preferring the camel case 1`] = ` Object { "could-be-either": "should be me", "couldBeEither": "should be me", } `; -exports[`CliUtils getOptValueFromProfiles should return args (with both cases) extracted from loaded profile, preferring the kebab case 1`] = ` +exports[`CliUtils getOptValuesFromConfig should return args (with both cases) extracted from loaded profile, preferring the kebab case 1`] = ` Object { "fake-string-opt": "should be me", "fakeStringOpt": "should be me", } `; -exports[`CliUtils getOptValueFromProfiles should return args with aliases if extracted option from a profile 1`] = ` +exports[`CliUtils getOptValuesFromConfig should return args with aliases if extracted option from a profile 1`] = ` Object { "w": "should have 'w' on args object too", "with-alias": "should have 'w' on args object too", @@ -126,21 +126,21 @@ Object { } `; -exports[`CliUtils getOptValueFromProfiles should return args with both cases, if the option is camel and the profile is kebab 1`] = ` +exports[`CliUtils getOptValuesFromConfig should return args with both cases, if the option is camel and the profile is kebab 1`] = ` Object { "could-be-either": "should be me", "couldBeEither": "should be me", } `; -exports[`CliUtils getOptValueFromProfiles should return args with both cases, if the option is kebab and the profile is camel 1`] = ` +exports[`CliUtils getOptValuesFromConfig should return args with both cases, if the option is kebab and the profile is camel 1`] = ` Object { "fake-string-opt": "should be me", "fakeStringOpt": "should be me", } `; -exports[`CliUtils getOptValueFromProfiles should throw an imperative error if a required profile is not present 1`] = `"Profile of type \\"banana\\" does not exist within the loaded profiles for the command and it is marked as required."`; +exports[`CliUtils getOptValuesFromConfig should throw an imperative error if a required profile is not present 1`] = `"Profile of type \\"banana\\" does not exist within the loaded profiles for the command and it is marked as required."`; exports[`CliUtils setOptionValue should include aliases in the returned args object 1`] = ` Object { diff --git a/packages/imperative/src/utilities/__tests__/diff/WebDiffManager.unit.test.ts b/packages/imperative/src/utilities/__tests__/diff/WebDiffManager.unit.test.ts index 397e6169f6..1efec863bf 100644 --- a/packages/imperative/src/utilities/__tests__/diff/WebDiffManager.unit.test.ts +++ b/packages/imperative/src/utilities/__tests__/diff/WebDiffManager.unit.test.ts @@ -26,8 +26,6 @@ describe("WebDiffManager", () => { const fakePatchDiff = "test"; const cliHome: string = "packages/__tests__/fakeCliHome"; const webDiffDir: string = path.join(cliHome, 'web-diff'); - // eslint-disable-next-line deprecation/deprecation - const mainModule = process.mainModule; beforeAll(async () => { const configs: IImperativeConfig = { @@ -37,11 +35,6 @@ describe("WebDiffManager", () => { }; - // eslint-disable-next-line deprecation/deprecation - (process.mainModule as any) = { - filename: "fakeCliCmd" - }; - Object.defineProperty(ImperativeConfig.instance, "cliHome", { configurable: true, get: jest.fn(() => { @@ -53,8 +46,6 @@ describe("WebDiffManager", () => { await Imperative.init(configs); }); afterAll(() => { - // eslint-disable-next-line deprecation/deprecation - process.mainModule = mainModule; // removing test dir generated by the test const rimraf = require('rimraf'); rimraf.sync('packages/__tests__'); diff --git a/packages/imperative/src/utilities/src/CliUtils.ts b/packages/imperative/src/utilities/src/CliUtils.ts index ca5260925c..951145064e 100644 --- a/packages/imperative/src/utilities/src/CliUtils.ts +++ b/packages/imperative/src/utilities/src/CliUtils.ts @@ -14,14 +14,13 @@ import { Constants } from "../../constants"; import { Arguments } from "yargs"; import { TextUtils } from "./TextUtils"; import { IOptionFormat } from "./doc/IOptionFormat"; -import { CommandProfiles, ICommandOptionDefinition, ICommandPositionalDefinition, - ICommandProfile, IHandlerParameters -} from "../../cmd"; +import { ICommandOptionDefinition, ICommandPositionalDefinition, ICommandProfile, IHandlerParameters } from "../../cmd"; import { ICommandArguments } from "../../cmd/src/doc/args/ICommandArguments"; -import { IProfile } from "../../profiles"; -import * as prompt from "readline-sync"; -import * as os from "os"; +import { ProfileUtils } from "../../profiles/src/utils/ProfileUtils"; import { IPromptOptions } from "../../cmd/src/doc/response/api/handler/IPromptOptions"; +import { read } from "read"; +import { ICommandDefinition } from "../../cmd"; +import { Config } from "../../config"; /** * Cli Utils contains a set of static methods/helpers that are CLI related (forming options, censoring args, etc.) @@ -51,7 +50,7 @@ export class CliUtils { * @returns {string} - e.g. --my-option */ public static getDashFormOfOption(optionName: string): string { - if ((optionName !== undefined && optionName !== null) && optionName.length >= 1) { + if (optionName !== undefined && optionName !== null && optionName.length >= 1) { const dashes = optionName.length > 1 ? Constants.OPT_LONG_DASH : Constants.OPT_SHORT_DASH; return dashes + optionName; } else { @@ -102,15 +101,11 @@ export class CliUtils { return newArgs; } - /** - * Accepts the full set of loaded profiles and attempts to match the option names supplied with profile keys. - * - * @param {Map} profileMap - the map of type to loaded profiles. The key is the profile type - * and the value is an array of profiles loaded for that type. - * - * @param {definitions} definitions - the profile definition on the command. - * + * Searches properties in team configuration and attempts to match the option names supplied with profile keys. + * @param {Config} config - Team config API + * @param {ICommandProfile} profileDef - Profile definition of invoked command + * @param {ICommandArguments} args - Arguments from command line and environment * @param {(Array)} options - the full set of command options * for the command being processed * @@ -118,72 +113,74 @@ export class CliUtils { * * @memberof CliUtils */ - public static getOptValueFromProfiles(profiles: CommandProfiles, definitions: ICommandProfile, + public static getOptValuesFromConfig(config: Config, profileDef: ICommandProfile, args: ICommandArguments, options: Array): any { - let args: any = {}; - - // Construct the precedence order to iterate through the profiles - let profileOrder: any = (definitions.required != null) ? definitions.required : []; - if (definitions.optional != null) { - profileOrder = profileOrder.concat(definitions.optional); + // Build a list of all profile types - this will help us search the CLI + // options for profiles specified by the user + let allTypes: string[] = []; + if (profileDef != null) { + if (profileDef.required != null) + allTypes = allTypes.concat(profileDef.required); + if (profileDef.optional != null) + allTypes = allTypes.concat(profileDef.optional); } - // Iterate through the profiles in the order they appear in the list provided. For each profile found, we will - // attempt to match the option name to a profile property exactly - and extract the value from the profile. - profileOrder.forEach((profileType: string) => { - - // Get the first profile loaded - for now, we won't worry about profiles and double-type loading for dependencies - // eslint-disable-next-line deprecation/deprecation - const profile: IProfile = profiles.get(profileType, false); - if (profile == null && definitions.required != null && definitions.required.indexOf(profileType) >= 0) { + // Build an object that contains all the options loaded from config + let fromCnfg: any = {}; + for (const profileType of allTypes) { + const opt = ProfileUtils.getProfileOptionAndAlias(profileType)[0]; + // If the config contains the requested profiles, then "remember" + // that this type has been fulfilled - so that we do NOT load from + // the traditional profile location + const profileTypePrefix = profileType + "_"; + let p: any = null; + if (args[opt] != null && config.api.profiles.exists(args[opt])) { + p = config.api.profiles.get(args[opt]); + } else if (args[opt] != null && !args[opt].startsWith(profileTypePrefix) && + config.api.profiles.exists(profileTypePrefix + args[opt])) { + p = config.api.profiles.get(profileTypePrefix + args[opt]); + } else if (args[opt] == null && + config.properties.defaults[profileType] != null && + config.api.profiles.exists(config.properties.defaults[profileType])) { + p = config.api.profiles.defaultGet(profileType); + } + if (p == null && profileDef.required != null && profileDef.required.indexOf(profileType) >= 0) { throw new ImperativeError({ msg: `Profile of type "${profileType}" does not exist within the loaded profiles for the command and it is marked as required.`, additionalDetails: `This is an internal imperative error. ` + `Command preparation was attempting to extract option values from this profile.` }); - } else if (profile != null) { - // For each option - extract the value if that exact property exists - options.forEach((opt) => { - let cases; - if (profile[opt.name] == null && "aliases" in opt) { - // Use aliases for backwards compatibility - // Search for first alias available in the profile - const oldOption = opt.aliases.find(o => profile[o] != null); - // Get the camel an kebab case - if (oldOption) cases = CliUtils.getOptionFormat(oldOption); - } - - if (cases == null) { - cases = CliUtils.getOptionFormat(opt.name); - } + } + fromCnfg = { ...p ?? {}, ...fromCnfg }; + } - // We have to "deal" with the situation that the profile contains both cases - camel and kebab. - // This is to support where the profile options have "-", but the properties are camel case in the - // yaml file - which is currently how most imperative CLIs have it coded. - const profileKebab = profile[cases.kebabCase]; - const profileCamel = profile[cases.camelCase]; - - // If the profile has either type (or both specified) we'll add it to args if the args object - // does NOT already contain the value in any case - if ((profileCamel !== undefined || profileKebab !== undefined) && - (!Object.prototype.hasOwnProperty.call(args, cases.kebabCase) && - !Object.prototype.hasOwnProperty.call(args, cases.camelCase))) { - - // If both case properties are present in the profile, use the one that matches - // the option name explicitly - const value = (profileKebab !== undefined && profileCamel !== undefined) ? - ((opt.name === cases.kebabCase) ? profileKebab : profileCamel) : - ((profileKebab !== undefined) ? profileKebab : profileCamel); - const keys = CliUtils.setOptionValue(opt.name, - ("aliases" in opt) ? (opt as ICommandOptionDefinition).aliases : [], - value - ); - args = {...args, ...keys}; - } - }); + // Convert each property extracted from the config to the correct yargs + // style cases for the command handler (kebab and camel) + options.forEach((opt) => { + let cases = CliUtils.getOptionFormat(opt.name); + if (fromCnfg[opt.name] == null && "aliases" in opt) { + // Use aliases for backwards compatibility + // Search for first alias available in the profile + const oldOption = opt.aliases.find(o => fromCnfg[o] != null); + // Get the camel and kebab case + if (oldOption) cases = CliUtils.getOptionFormat(oldOption); + } + const profileKebab = fromCnfg[cases.kebabCase]; + const profileCamel = fromCnfg[cases.camelCase]; + + if ((profileCamel !== undefined || profileKebab !== undefined) && + (!Object.hasOwn(args, cases.kebabCase) && !Object.hasOwn(args, cases.camelCase))) { + + // If both case properties are present in the profile, use the one that matches + // the option name explicitly + const shouldUseKebab = profileKebab !== undefined && profileCamel !== undefined ? + opt.name === cases.kebabCase : profileKebab !== undefined; + const value = shouldUseKebab ? profileKebab : profileCamel; + const keys = CliUtils.setOptionValue(opt.name, "aliases" in opt ? opt.aliases : [], value); + fromCnfg = { ...fromCnfg, ...keys }; } }); - return args; + return fromCnfg; } /** @@ -258,7 +255,7 @@ export class CliUtils { } const keys = CliUtils.setOptionValue(opt.name, - ("aliases" in opt) ? (opt as ICommandOptionDefinition).aliases : [], + "aliases" in opt ? (opt as ICommandOptionDefinition).aliases : [], envValue ); args = {...args, ...keys}; @@ -370,6 +367,21 @@ export class CliUtils { return TextUtils.chalk[color](headerText); } + public static generateDeprecatedMessage(cmdDefinition: ICommandDefinition, showWarning?: boolean): string { + + let message = ""; + if (cmdDefinition.deprecatedReplacement != null) { + const noNewlineInText = cmdDefinition.deprecatedReplacement.replace(/\n/g, " "); + if(showWarning) message += "\n\nWarning: This " + cmdDefinition.type + " has been deprecated.\n"; + if (cmdDefinition.deprecatedReplacement === "") { + message += "Obsolete component. No replacement exists"; + } else { + message += "Recommended replacement: " + noNewlineInText; + } + } + return message; + } + /** * Display a message when the command is deprecated. * @static @@ -383,15 +395,9 @@ export class CliUtils { const oldCmd = handlerParms.positionals.join(" "); // display the message handlerParms.response.console.error("\nWarning: The command '" + oldCmd + "' is deprecated."); - if(handlerParms.definition.deprecatedReplacement === "") - { - handlerParms.response.console.error("Obsolete component. No replacement exists"); - } - else - { - handlerParms.response.console.error("Recommended replacement: " + - handlerParms.definition.deprecatedReplacement); - } + // Use consolidated deprecated message logic + const deprecatedMessage = CliUtils.generateDeprecatedMessage(handlerParms.definition); + handlerParms.response.console.error(deprecatedMessage); } } @@ -438,20 +444,6 @@ export class CliUtils { return args; } - /** - * Display a prompt that hides user input and reads from stdin - * DOES NOT WORK WITH COMMANDS THAT ALSO READ STDIN - * Useful for prompting the user for sensitive info such as passwords - * Synchronous - * @deprecated Use the asynchronous method `readPrompt` instead - * @param message - The message to display to the user e.g. "Please enter password:" - * @returns value - the value entered by the user - */ - public static promptForInput(message: string): string { - prompt.setDefaultOptions({mask: "", hideEchoBack: true}); - return prompt.question(message); - } - /** * Sleep for the specified number of miliseconds. * @param timeInMs Number of miliseconds to sleep @@ -466,98 +458,6 @@ export class CliUtils { }); } - /** - * Prompt the user with a question and wait for an answer, - * but only up to the specified timeout. - * - * @deprecated Use `readPrompt` instead which supports more options - * @param questionText The text with which we will prompt the user. - * - * @param hideText Should we hide the text. True = display stars. - * False = display text. Default = false. - * - * @param secToWait The number of seconds that we will wait for an answer. - * If not supplied, the default is 600 seconds. - * - * @return A string containing the user's answer, or null if we timeout. - * - * @example - * const answer = await CliUtils.promptWithTimeout("Type your answer here: "); - * if (answer === null) { - * // abort the operation that you wanted to perform - * } else { - * // use answer in some operation - * } - */ - public static async promptWithTimeout( - questionText: string, - hideText: boolean = false, - secToWait: number = 600, - ): Promise { - - // readline provides our interface for terminal I/O - const readline = require("readline"); - const ttyIo = readline.createInterface({ - input: process.stdin, - output: process.stdout, - terminal: true, - prompt: questionText - }); - const writeToOutputOrig = ttyIo._writeToOutput; - - // ask user the desired question and then asynchronously read answer - ttyIo.prompt(); - let answerToReturn: string = null; - ttyIo.on("line", (answer: string) => { - answerToReturn = answer; - ttyIo.close(); - }).on("close", () => { - if (hideText) { - // The user's Enter key was echoed as a '*', so now output a newline - ttyIo._writeToOutput = writeToOutputOrig; - ttyIo.output.write("\n"); - } - }); - - // when asked to hide text, override output to only display stars - if (hideText) { - ttyIo._writeToOutput = function _writeToOutput(stringToWrite: string) { - if (stringToWrite === os.EOL) { - return; - } - if (stringToWrite.length === 1) { - // display a star for each one character of the hidden response - ttyIo.output.write("*"); - } else { - /* After a backspace, we get a string with the whole question - * and the hidden response. Redisplay the prompt and hide the response. - */ - let stringToShow = stringToWrite.substring(0, questionText.length); - for (let count = 1; count <= stringToWrite.length - questionText.length; count ++) { - stringToShow += "*"; - } - ttyIo.output.write(stringToShow); - } - }; - } - - // Ensure that we use a reasonable timeout - const maxSecToWait = 900; // 15 minute max - if (secToWait > maxSecToWait || secToWait <= 0) { - secToWait = maxSecToWait; - } - - // loop until timeout, to give our earlier asynch read a chance to work - const oneSecOfMillis = 1000; - for (let count = 1; answerToReturn === null && count <= secToWait; count++) { - await CliUtils.sleep(oneSecOfMillis); - } - - // terminate our use of the ttyIo object - ttyIo.close(); - return answerToReturn; - } - /** * Prompt the user with a question and wait for an answer, * but only up to the specified timeout. @@ -593,27 +493,30 @@ export class CliUtils { secToWait = maxSecToWait; } - return new Promise((resolve, reject) => { - require("read")({ + let response: string; + try { + response = await read({ input: process.stdin, output: process.stdout, terminal: true, prompt: message, silent: opts?.hideText, replace: opts?.maskChar, - timeout: secToWait ? (secToWait * 1000) : null // eslint-disable-line @typescript-eslint/no-magic-numbers - }, (error: any, result: string) => { - if (error == null) { - resolve(result); - } else if (error.message === "canceled") { - process.exit(2); - } else if (error.message === "timed out") { - resolve(null); - } else { - reject(error); - } + timeout: secToWait ? secToWait * 1000 : null // eslint-disable-line @typescript-eslint/no-magic-numbers }); - }); + if (opts?.hideText) { + process.stdout.write("\r\n"); + } + } catch (err) { + if (err.message === "canceled") { + process.exit(2); + } else if (err.message === "timed out") { + return null; + } else { + throw err; + } + } + return response; } /** diff --git a/packages/imperative/src/utilities/src/EnvFileUtils.ts b/packages/imperative/src/utilities/src/EnvFileUtils.ts index f6f3b0582c..e643407ac4 100644 --- a/packages/imperative/src/utilities/src/EnvFileUtils.ts +++ b/packages/imperative/src/utilities/src/EnvFileUtils.ts @@ -43,7 +43,8 @@ export class EnvFileUtils { if (expectedFileLocation) { try { const fileContents = readFileSync(expectedFileLocation).toString(); // Read the file in - const fileContentsJSON = JSONC.parse(fileContents); + // Typecasting because of this issue: https://github.com/kaelzhang/node-comment-json/issues/42 + const fileContentsJSON = JSONC.parse(fileContents) as any; this.environmentJSON = fileContentsJSON; this.resetEnvironmentForApp(); } catch (err) { diff --git a/packages/imperative/src/utilities/src/ImperativeConfig.ts b/packages/imperative/src/utilities/src/ImperativeConfig.ts index 2b0d4cdbc4..7d49569448 100644 --- a/packages/imperative/src/utilities/src/ImperativeConfig.ts +++ b/packages/imperative/src/utilities/src/ImperativeConfig.ts @@ -17,6 +17,7 @@ import { EnvironmentalVariableSettings } from "../../imperative/src/env/Environm import { IDaemonContext } from "../../imperative/src/doc/IDaemonContext"; import { ICommandProfileSchema } from "../../cmd"; import { Config } from "../../config"; +import { sync } from "find-up"; /** * This class is used to contain all configuration being set by Imperative. @@ -81,11 +82,11 @@ export class ImperativeConfig { private mConfig: Config; /** - * Gets a single instance of the PluginIssues. On the first call of - * ImperativeConfig.instance, a new Plugin Issues object is initialized and returned. + * Gets a single instance of the ImperativeConfig. On the first call of + * ImperativeConfig.instance, a new ImperativeConfig object is initialized and returned. * Every subsequent call will use the one that was first created. * - * @returns {ImperativeConfig} The newly initialized PMF object. + * @returns {ImperativeConfig} The newly initialized ImperativeConfig object. */ public static get instance(): ImperativeConfig { if (this.mInstance == null) { @@ -273,7 +274,7 @@ export class ImperativeConfig { // try to locate the file using find-up first let findupErr: Error; try { - const filePath = require("find-up").sync(file, {cwd: ImperativeConfig.instance.callerLocation}); + const filePath = sync(file, {cwd: ImperativeConfig.instance.callerLocation}); return require(filePath); } catch (e) { // couldn't locate using find-up, try to require directly diff --git a/packages/imperative/src/utilities/src/NextVerFeatures.ts b/packages/imperative/src/utilities/src/NextVerFeatures.ts index d5e28e6f0d..2c169a78a3 100644 --- a/packages/imperative/src/utilities/src/NextVerFeatures.ts +++ b/packages/imperative/src/utilities/src/NextVerFeatures.ts @@ -19,13 +19,15 @@ export class NextVerFeatures { private static ENV_VAR_PREFIX = "ZOWE"; /** + * This feature has already been incorporated into Zowe. We left this function + * in the source as a model for enabling a similar preview feature in the future. + * * Identify if we should use the V3 error message format. * That choice is determined by the value of the ZOWE_V3_ERR_FORMAT environment variable. * - * TODO:V3_ERR_FORMAT - Remove in V3 - * * @returns {boolean} True -> Use the V3 format. */ + /* public static useV3ErrFormat(): boolean { // our default is false let v3ErrFmtBoolVal: boolean = false; @@ -38,4 +40,5 @@ export class NextVerFeatures { } return v3ErrFmtBoolVal; } + */ } diff --git a/packages/imperative/src/utilities/src/ProcessUtils.ts b/packages/imperative/src/utilities/src/ProcessUtils.ts index d1b571abca..38e6332951 100644 --- a/packages/imperative/src/utilities/src/ProcessUtils.ts +++ b/packages/imperative/src/utilities/src/ProcessUtils.ts @@ -9,10 +9,7 @@ * */ -import { SpawnSyncOptions } from "child_process"; -import { ExecUtils } from "./ExecUtils"; import { Logger } from "../../logger"; -import { ImperativeConfig } from "./ImperativeConfig"; import { ISystemInfo } from "./doc/ISystemInfo"; import * as spawn from "cross-spawn"; @@ -123,18 +120,12 @@ export class ProcessUtils { * Open a file in the best editor that can be found in the current * environment. In a graphical environment, the default application * associated with its file extension will be launched. In a command-line - * environment, the file will be opened in vi, or the editor in the - * the `{envVariablePrefix}_EDITOR` environment variable if specified. + * environment, the file will be opened in vi. * @param filePath - File path to edit - * @param editorOpt - Chosen editor, can be a path or a valid environment variable name + * @param editor - Program name of editor to override the default (e.g., notepad) * @param sync - Boolean where true == synchronous and false == asynchronous */ - public static openInEditor(filePath: string, editorOpt?: string, sync?: boolean) { - let editor = editorOpt; - if (!editorOpt && ImperativeConfig.instance.loadedConfig.envVariablePrefix != null) { - const editorEnvVar = `${ImperativeConfig.instance.loadedConfig.envVariablePrefix}_EDITOR`; - if (process.env[editorEnvVar] != null) { editor = process.env[editorEnvVar]; } - } + public static openInEditor(filePath: string, editor?: string, sync?: boolean) { if (ProcessUtils.isGuiAvailable() === GuiResult.GUI_AVAILABLE) { Logger.getImperativeLogger().info(`Opening ${filePath} in graphical editor`); if (editor != null) { @@ -148,16 +139,4 @@ export class ProcessUtils { (sync ? spawn.sync : spawn.spawn)(editor, [filePath], { stdio: "inherit" }); } } - - /** - * Spawn a process with arguments and throw an error if the process fails. - * Parameters are same as `child_process.spawnSync` (see Node.js docs). - * Use this method if you want the safe argument parsing of `spawnSync` - * combined with the smart output handling of `execSync`. - * @deprecated Use ExecUtils.spawnAndGetOutput instead. - * @returns Contents of stdout as buffer or string - */ - public static execAndCheckOutput(command: string, args?: string[], options?: SpawnSyncOptions): Buffer | string { - return ExecUtils.spawnAndGetOutput(command, args, options); - } } \ No newline at end of file diff --git a/packages/imperative/src/utilities/src/TextUtils.ts b/packages/imperative/src/utilities/src/TextUtils.ts index dd59bc4631..1c8e3ff54d 100644 --- a/packages/imperative/src/utilities/src/TextUtils.ts +++ b/packages/imperative/src/utilities/src/TextUtils.ts @@ -36,11 +36,14 @@ export class TextUtils { * by the user's terminal * @returns {number} - the width that will work best for the user's terminal */ - public static getRecommendedWidth(preferredWidth: number = TextUtils.DEFAULT_WRAP_WIDTH): number { + public static getRecommendedWidth( + preferredWidth: number = process?.stdout?.columns ? process.stdout.columns : TextUtils.DEFAULT_WRAP_WIDTH + ): number { const widthSafeGuard = 8; // prevent partial words from continuing over lines const yargs = require("yargs"); - const maxWidth = (!(yargs.terminalWidth() == null) && yargs.terminalWidth() > 0) ? - (yargs.terminalWidth() - widthSafeGuard) : preferredWidth; + // eslint-disable-next-line no-extra-parens + const maxWidth = (yargs.terminalWidth() != null && yargs.terminalWidth() > 0) ? + yargs.terminalWidth() - widthSafeGuard : preferredWidth; return Math.min(preferredWidth, maxWidth); } @@ -129,7 +132,7 @@ export class TextUtils { /** * Default options for printing prettyJson */ - const defaultOptions = (!color || process.env.FORCE_COLOR === "0") ? { + const defaultOptions = !color || process.env.FORCE_COLOR === "0" ? { noColor: true } : { keysColor: "yellow" @@ -283,13 +286,13 @@ export class TextUtils { } catch (e) { // not json } - return (typeof value === 'string') || (typeof value === 'number') || isJson; + return typeof value === 'string' || typeof value === 'number' || isJson; }; if (Array.isArray(values) && values.filter(isPrintfValue).length === values.length) { - message = format.apply(this, [message].concat(values)); + message = format.apply(this, [message, ...values]); } else { - message = TextUtils.renderWithMustache.apply(this, [message].concat(values)); + message = TextUtils.renderWithMustache.apply(this, [message, ...values]); } } return message; @@ -300,14 +303,14 @@ export class TextUtils { const mChalk = require("chalk"); // chalk is supposed to handle this, but I think it only does so the first time it is loaded // so we need to check ourselves in case we've changed the environmental variables - if (process.env.FORCE_COLOR != null && ["1", "2", "3", "true"].includes(process.env.FORCE_COLOR)) { mChalk.enabled = true; } - if (process.env.MARKDOWN_GEN != null || process.env.FORCE_COLOR == "0") { mChalk.enabled = false; } - if (!mChalk.enabled) { mChalk.level = 0; } + if (process.env.MARKDOWN_GEN != null) { mChalk.level = 0; } else if (process.env.FORCE_COLOR != null) { const parsedInt = parseInt(process.env.FORCE_COLOR); // eslint-disable-next-line @typescript-eslint/no-magic-numbers if (!isNaN(parsedInt) && parsedInt >= 0 && parsedInt <= 3) { mChalk.level = parsedInt; + } else if (process.env.FORCE_COLOR === "true") { + mChalk.level = 1; } } @@ -328,7 +331,7 @@ export class TextUtils { const numberOfCommas = (keysAndValues.match(/[^\\],/g) || []).length; if (!/[^\\]=/g.test(keysAndValues) || - (numberOfEqualsSigns > 1 && numberOfCommas !== (numberOfEqualsSigns - 1)) + numberOfEqualsSigns > 1 && numberOfCommas !== numberOfEqualsSigns - 1 ) { throw new Error("The keys and values provided are not in the expected format. Example of expected format: " + keyValueExample); } diff --git a/packages/imperative/src/utilities/src/__mocks__/ImperativeConfig.ts b/packages/imperative/src/utilities/src/__mocks__/ImperativeConfig.ts index f6535abce4..492983bae1 100644 --- a/packages/imperative/src/utilities/src/__mocks__/ImperativeConfig.ts +++ b/packages/imperative/src/utilities/src/__mocks__/ImperativeConfig.ts @@ -43,7 +43,7 @@ export class ImperativeConfig { } public get callerPackageJson(): any { - return {version: 10000, name: "sample"}; + return {version: 10000, zoweVersion: "V99", name: "sample"}; } public get cliHome(): string { diff --git a/packages/imperative/tsconfig-tests.json b/packages/imperative/tsconfig-tests.json new file mode 100644 index 0000000000..3485999e7b --- /dev/null +++ b/packages/imperative/tsconfig-tests.json @@ -0,0 +1,40 @@ +{ + "compilerOptions": { + "types": [ + "node", + "jest" + ], + "lib": [ + "esnext" + ], + "experimentalDecorators": true, + "target": "es2015", + "module": "commonjs", + "noEmit": true, + "declaration": true, + "moduleResolution": "node", + "noImplicitAny": true, + "outDir": "./lib", + "preserveConstEnums": true, + "removeComments": false, + "pretty": true, + "sourceMap": true, + "newLine": "lf" + }, + "typeRoots": [ + "./node_modules/@types" + ], + "include": [ + "**/__tests__/*", + "**/__tests__/**/*", + "**/__mocks__/*" + ], + "exclude": [ + "lib", + "node_modules" + ], + "files": [ + "../../__types__/wontache.d.ts" + ], + "allowJs": true +} diff --git a/packages/imperative/tsconfig.json b/packages/imperative/tsconfig.json index fdfdb95a1d..511d8c8e52 100644 --- a/packages/imperative/tsconfig.json +++ b/packages/imperative/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "./lib" + "outDir": "./lib", + "stripInternal": true }, "include": [ "./src" diff --git a/packages/imperative/typedoc.json b/packages/imperative/typedoc.json index 2b97359f2c..b15f87adc5 100644 --- a/packages/imperative/typedoc.json +++ b/packages/imperative/typedoc.json @@ -1,5 +1,6 @@ { "out": "./docs/typedoc/", - "exclude": "**/__tests__/**", + "exclude": ["**/__tests__/**"], + "entryPoints": ["src/index.ts"], "cleanOutputDir": true } \ No newline at end of file diff --git a/packages/provisioning/CHANGELOG.md b/packages/provisioning/CHANGELOG.md index da89c6c8ef..02a0afa2ee 100644 --- a/packages/provisioning/CHANGELOG.md +++ b/packages/provisioning/CHANGELOG.md @@ -2,6 +2,35 @@ All notable changes to the Zowe provisioning SDK package will be documented in this file. +## Recent Changes + +- Update: Final prerelease + +## `8.0.0-next.202408131445` + +- Update: See `7.28.3` for details + +## `8.0.0-next.202403041352` + +- BugFix: Updated engine to Node 18.12.0. [#2074](https://github.com/zowe/zowe-cli/pull/2074) + +## `8.0.0-next.202402261705` + +- BugFix: Updated additional dependencies for technical currency. [#2061](https://github.com/zowe/zowe-cli/pull/2061) +- BugFix: Updated engine to Node 16.7.0. [#2061](https://github.com/zowe/zowe-cli/pull/2061) + +## `8.0.0-next.202402211923` + +- BugFix: Updated dependencies for technical currency. [#2057](https://github.com/zowe/zowe-cli/pull/2057) + +## `8.0.0-next.202311282012` + +- LTS Breaking: Unpinned dependency versions to allow for patch/minor version updates for dependencies [#1968](https://github.com/zowe/zowe-cli/issues/1968) + +## `8.0.0-next.202311132045` + +- Major: First major version bump for V3 + ## `7.28.3` - BugFix: Refactored code to reduce the use of deprecated functions to prepare for upcoming Node.js 22 support. [#2191](https://github.com/zowe/zowe-cli/issues/2191) diff --git a/packages/provisioning/__tests__/__system__/ListInstanceInfo.system.test.ts b/packages/provisioning/__tests__/__system__/ListInstanceInfo.system.test.ts index 2c1f99dcb1..509353b2d5 100644 --- a/packages/provisioning/__tests__/__system__/ListInstanceInfo.system.test.ts +++ b/packages/provisioning/__tests__/__system__/ListInstanceInfo.system.test.ts @@ -43,6 +43,7 @@ describe("ListInstanceInfo.listInstanceCommon", () => { templateName); instanceID = instance["object-id"]; Imperative.console.info(`Provisioned instance: ${instance["external-name"]}`); + if (instanceID == null) { throw Error("Cannot continue test - instance ID is undefined"); } }); afterAll(async () => { diff --git a/packages/provisioning/__tests__/__system__/ListInstanceVariables.system.test.ts b/packages/provisioning/__tests__/__system__/ListInstanceVariables.system.test.ts index 4ad89b4de6..5bc226c766 100644 --- a/packages/provisioning/__tests__/__system__/ListInstanceVariables.system.test.ts +++ b/packages/provisioning/__tests__/__system__/ListInstanceVariables.system.test.ts @@ -42,6 +42,7 @@ describe("ListInstanceVariables (system)", () => { templateName); instanceID = instance["object-id"]; Imperative.console.info(`Provisioned instance: ${instance["external-name"]}`); + if (instanceID == null) { throw Error("Cannot continue test - instance ID is undefined"); } }); afterAll(async () => { diff --git a/packages/provisioning/__tests__/__system__/ListRegistryInstances.system.test.ts b/packages/provisioning/__tests__/__system__/ListRegistryInstances.system.test.ts index c509f14e7e..3737f60ac9 100644 --- a/packages/provisioning/__tests__/__system__/ListRegistryInstances.system.test.ts +++ b/packages/provisioning/__tests__/__system__/ListRegistryInstances.system.test.ts @@ -43,6 +43,7 @@ describe("ListRegistryInstances (system)", () => { instanceName = instance["external-name"]; instanceID = instance["object-id"]; Imperative.console.info(`Provisioned instance: ${instanceName}`); + if (instanceID == null) { throw Error("Cannot continue test - instance ID is undefined"); } }, ProvisioningTestUtils.MAX_TIMEOUT_TIME); afterAll(async () => { diff --git a/packages/provisioning/__tests__/__system__/PerformAction.system.test.ts b/packages/provisioning/__tests__/__system__/PerformAction.system.test.ts index 7ce4b4249b..84c27ed7d1 100644 --- a/packages/provisioning/__tests__/__system__/PerformAction.system.test.ts +++ b/packages/provisioning/__tests__/__system__/PerformAction.system.test.ts @@ -44,6 +44,7 @@ describe("PerformAction.doProvisioningActionCommon (system)", () => { templateName); instanceID = instance["object-id"]; Imperative.console.info(`Provisioned instance: ${instance["external-name"]}`); + if (instanceID == null) { throw Error("Cannot continue test - instance ID is undefined"); } }); afterAll(async () => { diff --git a/packages/provisioning/package.json b/packages/provisioning/package.json index ea0c9de969..e0e0ffd986 100644 --- a/packages/provisioning/package.json +++ b/packages/provisioning/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/provisioning-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "description": "Zowe SDK to interact with the z/OS provisioning APIs", "author": "Zowe", "license": "EPL-2.0", @@ -45,16 +45,19 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "js-yaml": "4.1.0" + "js-yaml": "^4.1.0" }, "devDependencies": { - "@types/js-yaml": "^4.0.5", - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" + "@types/js-yaml": "^4.0.9", + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" }, "peerDependencies": { - "@zowe/core-for-zowe-sdk": "^7.0.0", - "@zowe/imperative": "^5.0.0" + "@zowe/core-for-zowe-sdk": "^8.0.0-next", + "@zowe/imperative": "^8.0.0-next" + }, + "engines": { + "node": ">=18.12.0" } } diff --git a/packages/provisioning/typedoc.json b/packages/provisioning/typedoc.json index 2b97359f2c..b15f87adc5 100644 --- a/packages/provisioning/typedoc.json +++ b/packages/provisioning/typedoc.json @@ -1,5 +1,6 @@ { "out": "./docs/typedoc/", - "exclude": "**/__tests__/**", + "exclude": ["**/__tests__/**"], + "entryPoints": ["src/index.ts"], "cleanOutputDir": true } \ No newline at end of file diff --git a/packages/secrets/CHANGELOG.md b/packages/secrets/CHANGELOG.md index 054df8cec3..14f34dd0ff 100644 --- a/packages/secrets/CHANGELOG.md +++ b/packages/secrets/CHANGELOG.md @@ -2,6 +2,22 @@ All notable changes to the Zowe Secrets SDK package will be documented in this file. +## Recent Changes + +- Update: Final prerelease + +## `8.0.0-next.202407021516` + +- BugFix: Updated dependencies for technical currency [#2188](https://github.com/zowe/zowe-cli/pull/2188) + +## `8.0.0-next.202402211923` + +- BugFix: Updated dependencies for technical currency. [#2057](https://github.com/zowe/zowe-cli/pull/2057) + +## `8.0.0-next.202311132045` + +- Major: First major version bump for V3 + ## `7.18.6` - BugFix: Use `core-foundation-rs` instead of `security-framework` for macOS logic, as `security-framework` is now archived. [#1802](https://github.com/zowe/zowe-cli/issues/1802) @@ -23,7 +39,7 @@ All notable changes to the Zowe Secrets SDK package will be documented in this f ## `7.18.1` -- Added README to package w/ description, instructions and examples of using the `keyring` module. +- Added README to package w/ description, instructions and examples of using the `keyring` module. ## `7.18.0` diff --git a/packages/secrets/package.json b/packages/secrets/package.json index efcebdbbcc..800d59e57f 100644 --- a/packages/secrets/package.json +++ b/packages/secrets/package.json @@ -3,12 +3,11 @@ "description": "Credential management facilities for Imperative, Zowe CLI, and extenders.", "repository": "https://github.com/zowe/zowe-cli.git", "author": "Zowe", - "version": "7.28.3", + "version": "8.0.0-next.202409111528", "homepage": "https://github.com/zowe/zowe-cli/tree/master/packages/secrets#readme", "bugs": { "url": "https://github.com/zowe/zowe-cli/issues" }, - "private": true, "main": "lib/index.js", "types": "lib/index.d.ts", "files": [ @@ -25,14 +24,14 @@ }, "license": "EPL-2.0", "devDependencies": { - "@napi-rs/cli": "^2.16.2", - "ava": "^4.3.3" + "@napi-rs/cli": "^2.18.4", + "ava": "^6.0.0" }, "ava": { "timeout": "3m" }, "engines": { - "node": ">= 14" + "node": ">=14" }, "scripts": { "artifacts": "napi artifacts", diff --git a/packages/secrets/scripts/prebuildify.sh b/packages/secrets/scripts/prebuildify.sh index 9342d77029..1110810888 100644 --- a/packages/secrets/scripts/prebuildify.sh +++ b/packages/secrets/scripts/prebuildify.sh @@ -1,8 +1,10 @@ #!/bin/bash set -ex rm -rf prebuilds && mkdir -p prebuilds -SECRETS_BRANCH="${SECRETS_BRANCH:-master}" +if [ -z "$SECRETS_BRANCH" ]; then + SECRETS_BRANCH=$(git rev-parse --abbrev-ref HEAD) +fi SECRETS_WORKFLOW_ID=$(gh run list -b $SECRETS_BRANCH --limit 1 --status success --workflow "Secrets SDK CI" --json databaseId --jq ".[0].databaseId") echo "Downloading Secrets SDK prebuilds from $SECRETS_BRANCH branch..." gh run download $SECRETS_WORKFLOW_ID --dir prebuilds --pattern "bindings-*" -mv prebuilds/*/* prebuilds && rm -r prebuilds/*/ \ No newline at end of file +mv prebuilds/*/* prebuilds && rm -r prebuilds/*/ diff --git a/packages/secrets/typedoc.json b/packages/secrets/typedoc.json new file mode 100644 index 0000000000..b15f87adc5 --- /dev/null +++ b/packages/secrets/typedoc.json @@ -0,0 +1,6 @@ +{ + "out": "./docs/typedoc/", + "exclude": ["**/__tests__/**"], + "entryPoints": ["src/index.ts"], + "cleanOutputDir": true +} \ No newline at end of file diff --git a/packages/workflows/CHANGELOG.md b/packages/workflows/CHANGELOG.md index a7aa3f2085..cfc38196df 100644 --- a/packages/workflows/CHANGELOG.md +++ b/packages/workflows/CHANGELOG.md @@ -2,6 +2,27 @@ All notable changes to the Zowe z/OS workflows SDK package will be documented in this file. +## Recent Changes + +- Update: Final prerelease + +## `8.0.0-next.202408131445` + +- Update: See `7.28.3` for details + +## `8.0.0-next.202403041352` + +- BugFix: Updated engine to Node 18.12.0. [#2074](https://github.com/zowe/zowe-cli/pull/2074) + +## `8.0.0-next.202402261705` + +- BugFix: Updated dependencies for technical currency. [#2061](https://github.com/zowe/zowe-cli/pull/2061) +- BugFix: Updated engine to Node 16.7.0. [#2061](https://github.com/zowe/zowe-cli/pull/2061) + +## `8.0.0-next.202311132045` + +- Major: First major version bump for V3 + ## `7.28.3` - BugFix: Refactored code to reduce the use of deprecated functions to prepare for upcoming Node.js 22 support. [#2191](https://github.com/zowe/zowe-cli/issues/2191) diff --git a/packages/workflows/__tests__/__system__/Archive.system.test.ts b/packages/workflows/__tests__/__system__/Archive.system.test.ts index fe55f5d343..f930010fce 100644 --- a/packages/workflows/__tests__/__system__/Archive.system.test.ts +++ b/packages/workflows/__tests__/__system__/Archive.system.test.ts @@ -172,7 +172,7 @@ describe("Errors caused by the user interaction", () => { } catch (error) { Imperative.console.info(JSON.stringify(error)); expect(error.mDetails.errorCode).toEqual(404); - expect(error.message).toContain("IZUWF5001W"); + expect(error.causeErrors).toContain("IZUWF5001W"); // https://www.ibm.com/docs/en/zos/2.5.0?topic=izuwf9999-izuwf5001w } }); @@ -191,7 +191,7 @@ describe("Errors caused by the user interaction", () => { } catch (error) { Imperative.console.info(error); expect(error.mDetails.errorCode).toBe(409); - expect(error.message).toContain("IZUWF0158E"); + expect(error.causeErrors).toContain("IZUWF0158E"); // https://www.ibm.com/docs/en/zos/2.5.0?topic=izuwf9999-izuwf0158e } await removeWorkflows(); diff --git a/packages/workflows/__tests__/__system__/Cancel.system.test.ts b/packages/workflows/__tests__/__system__/Cancel.system.test.ts index 18b6c8e5ca..678e72b757 100644 --- a/packages/workflows/__tests__/__system__/Cancel.system.test.ts +++ b/packages/workflows/__tests__/__system__/Cancel.system.test.ts @@ -37,12 +37,18 @@ function expectZosmfResponseSucceeded(response: string, error: ImperativeError) expect(response).toBeDefined(); } -function expectZosmfResponseFailed(response: string, error: ImperativeError, msg: string) { +function expectZosmfResponseFailed(response: string, error: ImperativeError, msg:string) { expect(response).not.toBeDefined(); expect(error).toBeDefined(); expect(error.details.msg).toContain(msg); } +function expectZosmfResponseFailedCause(response: string, error: ImperativeError, msg: string) { + expect(response).not.toBeDefined(); + expect(error).toBeDefined(); + expect(error.causeErrors).toContain(msg); +} + describe("Cancel workflow", () => { beforeAll(async () => { testEnvironment = await TestEnvironment.setUp({ @@ -161,7 +167,7 @@ describe("Cancel workflow", () => { error = thrownError; Imperative.console.info(`Error ${error}`); } - expectZosmfResponseFailed(response, error, WrongWorkflowKey.message); + expectZosmfResponseFailedCause(response, error, WrongWorkflowKey.message); // parse from message the workflow key const actual: string = JSON.stringify(error); const expected: RegExp = /The workflow key .+ was not found/gm; diff --git a/packages/workflows/__tests__/__system__/api/Create.system.test.ts b/packages/workflows/__tests__/__system__/api/Create.system.test.ts index e697a8248a..69e3d3c143 100644 --- a/packages/workflows/__tests__/__system__/api/Create.system.test.ts +++ b/packages/workflows/__tests__/__system__/api/Create.system.test.ts @@ -236,7 +236,7 @@ describe("Create workflow", () => { it("Throws an error with wrong format of workflow definition file. Wrong member name.", async () => { const error = await produceError(REAL_SESSION, wfName, "DS.NAME(0)", system, owner); expect(error.errorCode).toEqual(notFound); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); }); describe("IZUWF0103E", () => { @@ -245,52 +245,52 @@ describe("Create workflow", () => { it("Throws an error with wrong format of workflow definition file.", async () => { const error = await produceError(REAL_SESSION, wfName, "wrongPath", system, owner); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); it("Throws an error with wrong format of workflow definition file. Name that ends with a period.", async () => { const error = await produceError(REAL_SESSION, wfName, "DS.NAME.", system, owner); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); it("Throws an error with wrong format of workflow definition file. Path not from root.", async () => { const error = await produceError(REAL_SESSION, wfName, "home/file", system, owner); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); it("Throws an error with wrong format of workflow definition file. Qualifier is longer than 8 characters.", async () => { const error = await produceError(REAL_SESSION, wfName, "DS.NAME.LONGFIELD", system, owner); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); it("Throws an error with wrong format of workflow definition file. More than 44 characters for DSNAME alone.", async () => { const error = await produceError(REAL_SESSION, wfName, "DS.NAME.STUFF.STUFF.STUFF.STUFF.STUFF.STUFF.STUFF.STUFF", system, owner); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); it("Throws an error with wrong format of workflow definition file. Name containing two successive periods.", async () => { const error = await produceError(REAL_SESSION, wfName, "DS..NAME", system, owner); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); it("Throws an error with wrong format of definition file. Name contains a qualifier that starts with numeric character.", async () => { const error = await produceError(REAL_SESSION, wfName, "DS.123.NAME", system, owner); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); it("Throws an error with wrong format of workflow definition file. Member name is too long.", async () => { const error = await produceError(REAL_SESSION, wfName, "DS.NAME(MEMBER123)", system, owner); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); it("Throws an error with wrong format of workflow definition file. Member doesn't end with `)`.", async () => { const error = await produceError(REAL_SESSION, wfName, "DS.NAME(MEMBER", system, owner); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); it("Throws an error with wrong format of workflow definition file. Name contains non-allowed character.", async () => { const error = await produceError(REAL_SESSION, wfName, "DS.NAME%", system, owner); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); }); describe("IZUWF0105E", () => { @@ -299,12 +299,12 @@ describe("Create workflow", () => { it("Throws an error with wrong format of variable input file. Name does not exist.", async () => { const error = await produceError(REAL_SESSION, wfName, definitionFile, system, owner, "DS.NAME.WRONG"); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); it("Throws an error with wrong format of variable input file. Wrong member name.", async () => { const error = await produceError(REAL_SESSION, wfName, definitionFile, system, owner, "DS.NAME(0)"); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); }); describe("IZUWF0107E", () => { @@ -313,33 +313,33 @@ describe("Create workflow", () => { it("Throws an error with wrong format of variable input file. Name that ends with a period.", async () => { const error = await produceError(REAL_SESSION, wfName, definitionFile, system, owner, "DS.NAME."); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); it("Throws an error with wrong format of variable input file. More than 44 characters for DSNAME alone.", async () => { const error = await produceError(REAL_SESSION, wfName, definitionFile, system, owner, "DS.NAME.STUFF.STUFF.STUFF.STUFF.STUFF.STUFF.STUFF.STUFF"); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); it("Throws an error with wrong format of variable input file. Name containing two successive periods.", async () => { const error = await produceError(REAL_SESSION, wfName, definitionFile, system, owner, "DS..NAME"); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); it("Name that contains a qualifier that starts with non-alphabetic or non-special character.", async () => { const error = await produceError(REAL_SESSION, wfName, definitionFile, system, owner, "DS.123.NAME"); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); it("Throws an error with wrong format of variable input file. Qualifier is longer than 8 characters.", async () => { const error = await produceError(REAL_SESSION, wfName, definitionFile, system, owner, "DS.NAME.LONGFIELD"); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); it("Throws an error with wrong format of variable input file. Path not from root.", async () => { const error = await produceError(REAL_SESSION, wfName, definitionFile, system, owner, "home/file"); expect(error.errorCode).toEqual(status400); - expect(error.message).toContain(messageId); + expect(error.causeErrors).toContain(messageId); }); }); }); diff --git a/packages/workflows/package.json b/packages/workflows/package.json index 38132b5567..092aeed8f1 100644 --- a/packages/workflows/package.json +++ b/packages/workflows/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-workflows-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "description": "Zowe SDK to interact with the z/OS workflows APIs", "author": "Zowe", "license": "EPL-2.0", @@ -45,15 +45,18 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.29.2" + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202409111528" }, "devDependencies": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" }, "peerDependencies": { - "@zowe/core-for-zowe-sdk": "^7.0.0", - "@zowe/imperative": "^5.0.0" + "@zowe/core-for-zowe-sdk": "^8.0.0-next", + "@zowe/imperative": "^8.0.0-next" + }, + "engines": { + "node": ">=18.12.0" } } diff --git a/packages/workflows/src/Create.ts b/packages/workflows/src/Create.ts index d3edd09072..d917d23bb8 100644 --- a/packages/workflows/src/Create.ts +++ b/packages/workflows/src/Create.ts @@ -209,7 +209,7 @@ export class CreateWorkflow{ await Upload.fileToUssFile(session, localFile, remoteFile, { binary: true }); } catch (error) { throw new ImperativeError({ - msg : "Failed to create temporary uss file\n" + (error.message) + "\n" + (error.additionalDetails) + msg : "Failed to create temporary uss file\n" + error.message + "\n" + error.additionalDetails }); } } diff --git a/packages/workflows/typedoc.json b/packages/workflows/typedoc.json index 2b97359f2c..b15f87adc5 100644 --- a/packages/workflows/typedoc.json +++ b/packages/workflows/typedoc.json @@ -1,5 +1,6 @@ { "out": "./docs/typedoc/", - "exclude": "**/__tests__/**", + "exclude": ["**/__tests__/**"], + "entryPoints": ["src/index.ts"], "cleanOutputDir": true } \ No newline at end of file diff --git a/packages/zosconsole/CHANGELOG.md b/packages/zosconsole/CHANGELOG.md index 7a98994933..1c712426f3 100644 --- a/packages/zosconsole/CHANGELOG.md +++ b/packages/zosconsole/CHANGELOG.md @@ -2,6 +2,27 @@ All notable changes to the Zowe z/OS console SDK package will be documented in this file. +## Recent Changes + +- Update: Final prerelease + +## `8.0.0-next.202408131445` + +- Update: See `7.28.3` for details + +## `8.0.0-next.202403041352` + +- BugFix: Updated engine to Node 18.12.0. [#2074](https://github.com/zowe/zowe-cli/pull/2074) + +## `8.0.0-next.202402261705` + +- BugFix: Updated dependencies for technical currency. [#2061](https://github.com/zowe/zowe-cli/pull/2061) +- BugFix: Updated engine to Node 16.7.0. [#2061](https://github.com/zowe/zowe-cli/pull/2061) + +## `8.0.0-next.202311132045` + +- Major: First major version bump for V3 + ## `7.28.3` - BugFix: Refactored code to reduce the use of deprecated functions to prepare for upcoming Node.js 22 support. [#2191](https://github.com/zowe/zowe-cli/issues/2191) diff --git a/packages/zosconsole/package.json b/packages/zosconsole/package.json index 150621b1a4..31ed4b40d3 100644 --- a/packages/zosconsole/package.json +++ b/packages/zosconsole/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-console-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "description": "Zowe SDK to interact with the z/OS console", "author": "Zowe", "license": "EPL-2.0", @@ -45,12 +45,15 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" }, "peerDependencies": { - "@zowe/core-for-zowe-sdk": "^7.0.0", - "@zowe/imperative": "^5.0.0" + "@zowe/core-for-zowe-sdk": "^8.0.0-next", + "@zowe/imperative": "^8.0.0-next" + }, + "engines": { + "node": ">=18.12.0" } } diff --git a/packages/zosconsole/src/ConsoleResponseService.ts b/packages/zosconsole/src/ConsoleResponseService.ts index 5318342395..b83e15ae55 100644 --- a/packages/zosconsole/src/ConsoleResponseService.ts +++ b/packages/zosconsole/src/ConsoleResponseService.ts @@ -57,8 +57,8 @@ export class ConsoleResponseService { // If there are messages append a line-break to ensure that additional messages collected are // displayed properly. if (response.commandResponse.length > 0 - && (response.commandResponse.indexOf("\n") - !== response.commandResponse.length - 1)) { + && response.commandResponse.indexOf("\n") + !== response.commandResponse.length - 1) { response.commandResponse += "\n"; } } diff --git a/packages/zosconsole/typedoc.json b/packages/zosconsole/typedoc.json index 2b97359f2c..b15f87adc5 100644 --- a/packages/zosconsole/typedoc.json +++ b/packages/zosconsole/typedoc.json @@ -1,5 +1,6 @@ { "out": "./docs/typedoc/", - "exclude": "**/__tests__/**", + "exclude": ["**/__tests__/**"], + "entryPoints": ["src/index.ts"], "cleanOutputDir": true } \ No newline at end of file diff --git a/packages/zosfiles/CHANGELOG.md b/packages/zosfiles/CHANGELOG.md index fe59a322f8..114bfe042f 100644 --- a/packages/zosfiles/CHANGELOG.md +++ b/packages/zosfiles/CHANGELOG.md @@ -2,6 +2,78 @@ All notable changes to the Zowe z/OS files SDK package will be documented in this file. +## Recent Changes + +- Update: Final prerelease + +## `8.0.0-next.202408131445` + +- Update: See `7.28.3` for details + +## `8.0.0-next.202407021516` + +- BugFix: Updated dependencies for technical currency [#2188](https://github.com/zowe/zowe-cli/pull/2188) + +## `8.0.0-next.202406111958` + +- LTS Breaking: Modified the zos-files SDK. [#2083](https://github.com/zowe/zowe-cli/issues/2083) + - Deprecated the following interfaces: + - IOptionsFullResponse - use `IOptionsFullResponse` from `@zowe/imperative`. + - IRestClientResponse - use `IRestClientResponse` from `@zowe/imperative`. + +## `8.0.0-next.202406111728` + +- BugFix: Fixed error where `Get.dataSet` and `Get.USSFile` methods could silently fail when downloading large data sets or files. [#2167](https://github.com/zowe/zowe-cli/pull/2167) + +## `8.0.0-next.202405202020` + +- BugFix: Fixed a bug where a data set search would not return a search term if it was at the beginning of a line. [#2147](https://github.com/zowe/zowe-cli/pull/2147) + +## `8.0.0-next.202405101931` + +- Enhancement: Added the ability to search for a string in a data set or PDS member matching a pattern. [#2095](https://github.com/zowe/zowe-cli/issues/2095) + +## `8.0.0-next.202404032038` + +- BugFix: Fixed error that could occur when listing data set members that contain control characters in the name. [#2104](https://github.com/zowe/zowe-cli/pull/2104) + +## `8.0.0-next.202403132009` + +- LTS Breaking: Changed return type of `Upload.bufferToUssFile` to return `IZosFilesResponse` object instead of string. [#2089](https://github.com/zowe/zowe-cli/pull/2089) +- BugFix: Fixed `Upload.bufferToUssFile` not normalizing new lines when uploading plain text. [#2089](https://github.com/zowe/zowe-cli/pull/2089) + +## `8.0.0-next.202403041352` + +- BugFix: Updated engine to Node 18.12.0. [#2074](https://github.com/zowe/zowe-cli/pull/2074) + +## `8.0.0-next.202402261705` + +- BugFix: Updated additional dependencies for technical currency. [#2061](https://github.com/zowe/zowe-cli/pull/2061) +- BugFix: Updated engine to Node 16.7.0. [#2061](https://github.com/zowe/zowe-cli/pull/2061) + +## `8.0.0-next.202402211923` + +- BugFix: Updated dependencies for technical currency. [#2057](https://github.com/zowe/zowe-cli/pull/2057) + +## `8.0.0-next.202402132108` + +- LTS Breaking: Removed record format (recfm) validation when creating data-sets [#1699](https://github.com/zowe/zowe-cli/issues/1699) + +## `8.0.0-next.202402021649` + +- LTS Breaking: Removed the unused protected property `mSshProfile` in SshBaseHandler. +- LTS Breaking: Removed the following previously deprecated items: + - Removed `ZosFilesCreateExtraOptions.showAttributes` without replacement + - Removed `allDataSetsArchived`, `datasetsDownloadedSuccessfully`, `noDataSetsMatchingPatternRemain` and `onlyEmptyPartitionedDataSets` from ZosFiles.messages.ts + +## `8.0.0-next.202311282012` + +- LTS Breaking: Unpinned dependency versions to allow for patch/minor version updates for dependencies [#1968](https://github.com/zowe/zowe-cli/issues/1968) + +## `8.0.0-next.202311132045` + +- Major: First major version bump for V3 + ## `7.28.3` - BugFix: Refactored code to reduce the use of deprecated functions to prepare for upcoming Node.js 22 support. [#2191](https://github.com/zowe/zowe-cli/issues/2191) diff --git a/packages/zosfiles/__tests__/__system__/methods/create/Create.system.test.ts b/packages/zosfiles/__tests__/__system__/methods/create/Create.system.test.ts index 8c3f470c3f..105fe7be10 100644 --- a/packages/zosfiles/__tests__/__system__/methods/create/Create.system.test.ts +++ b/packages/zosfiles/__tests__/__system__/methods/create/Create.system.test.ts @@ -240,8 +240,7 @@ describe("Allocate Like", () => { primary: 20, recfm: "FB", blksize: 6160, - lrecl: 80, - showAttributes: true + lrecl: 80 } as any; beforeAll(async () => { @@ -303,8 +302,7 @@ describe("Allocate Like - encoded", () => { primary: 20, recfm: "FB", blksize: 6160, - lrecl: 80, - showAttributes: true + lrecl: 80 } as any; beforeAll(async () => { diff --git a/packages/zosfiles/__tests__/__system__/methods/delete/DeleteZfs.system.test.ts b/packages/zosfiles/__tests__/__system__/methods/delete/DeleteZfs.system.test.ts index 9a0d5724fa..983827a193 100644 --- a/packages/zosfiles/__tests__/__system__/methods/delete/DeleteZfs.system.test.ts +++ b/packages/zosfiles/__tests__/__system__/methods/delete/DeleteZfs.system.test.ts @@ -129,7 +129,8 @@ describe("Delete a z/OS File System", () => { } expect(error).toBeDefined(); expect(response).toBeUndefined(); - expect(error.message).toContain("Error executing IDCAMS DELETE command. exit_code=8"); + expect(error.message).toContain(`ENTRY ${nonExistZfs.toUpperCase()} NOT FOUND`); + expect(error.message).toContain("FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 8"); }); }); diff --git a/packages/zosfiles/__tests__/__system__/methods/download/Download.system.test.ts b/packages/zosfiles/__tests__/__system__/methods/download/Download.system.test.ts index 7a5a9e51b7..2009a9b432 100644 --- a/packages/zosfiles/__tests__/__system__/methods/download/Download.system.test.ts +++ b/packages/zosfiles/__tests__/__system__/methods/download/Download.system.test.ts @@ -38,7 +38,7 @@ import * as fs from "fs"; import { posix } from "path"; import { Shell } from "@zowe/zos-uss-for-zowe-sdk"; import { PassThrough } from "stream"; -import getStream = require("get-stream"); +import { text } from "stream/consumers"; const rimraf = require("rimraf").sync; const delayTime = 2000; @@ -353,7 +353,7 @@ describe("Download Data Set", () => { ZosFilesMessages.datasetDownloadedSuccessfully.message.substring(0, "Data set downloaded successfully".length + 1)); // Compare the downloaded contents to those uploaded - const fileContents = stripNewLines(await getStream(responseStream)); + const fileContents = stripNewLines(await text(responseStream)); expect(fileContents).toEqual(testData); }); }); @@ -1006,7 +1006,7 @@ describe("Download Data Set", () => { const endpoint: string = ZosFilesConstants.RESOURCE + ZosFilesConstants.RES_USS_FILES + ussname; try { - (await ZosmfRestClient.deleteExpectString(REAL_SESSION, endpoint)); + await ZosmfRestClient.deleteExpectString(REAL_SESSION, endpoint); await delay(delayTime); } catch (err) { Imperative.console.error(err); @@ -1229,7 +1229,7 @@ describe("Download Data Set", () => { expect(response).toBeTruthy(); // Compare the downloaded contents to those uploaded - const fileContents = stripNewLines(await getStream(responseStream)); + const fileContents = stripNewLines(await text(responseStream)); expect(fileContents).toEqual(testData); }); }); @@ -1508,7 +1508,7 @@ describe("Download Data Set", () => { caughtError = error; } expect(caughtError).toBeDefined(); - expect(caughtError.message).toContain("Path name not found"); + expect(stripNewLines(caughtError.message)).toContain("Path name not found"); }); }); }); @@ -1793,7 +1793,7 @@ describe("Download Data Set - encoded", () => { const endpoint: string = ZosFilesConstants.RESOURCE + ZosFilesConstants.RES_USS_FILES + encodeURIComponent(ussname); try { - (await ZosmfRestClient.deleteExpectString(REAL_SESSION, endpoint)); + await ZosmfRestClient.deleteExpectString(REAL_SESSION, endpoint); await delay(delayTime); } catch (err) { Imperative.console.error(err); diff --git a/packages/zosfiles/__tests__/__system__/methods/search/Search.system.test.ts b/packages/zosfiles/__tests__/__system__/methods/search/Search.system.test.ts new file mode 100644 index 0000000000..34ba130ba8 --- /dev/null +++ b/packages/zosfiles/__tests__/__system__/methods/search/Search.system.test.ts @@ -0,0 +1,271 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { Session } from "@zowe/imperative"; +import { ITestEnvironment } from "@zowe/cli-test-utils"; +import { TestEnvironment } from "../../../../../../__tests__/__src__/environment/TestEnvironment"; +import { ITestPropertiesSchema } from "../../../../../../__tests__/__src__/properties/ITestPropertiesSchema"; +import { getUniqueDatasetName } from "../../../../../../__tests__/__src__/TestUtils"; +import { Create, Upload, Delete, Search, CreateDataSetTypeEnum, ISearchOptions, IZosFilesResponse } from "../../../../src"; + +let REAL_SESSION: Session; +let testEnvironment: ITestEnvironment; +let defaultSystem: ITestPropertiesSchema; + +let pattern: string; +let oldForceColor: string; + +const searchString = "Zowe CLI"; +const goodTestString = "This system test is brought to you by Zowe CLI!"; +const badTestString = "Sadly, this string will not match the search."; + +describe("Search", () => { + beforeAll(async () => { + testEnvironment = await TestEnvironment.setUp({ + testName: "zos_files_search" + }); + defaultSystem = testEnvironment.systemTestProperties; + REAL_SESSION = TestEnvironment.createZosmfSession(testEnvironment); + + // We can't test color related stuff in GitHub Actions or Jenkins + oldForceColor = process.env.FORCE_COLOR; + process.env.FORCE_COLOR = "0"; + }); + + afterAll(async () => { + process.env.FORCE_COLOR = oldForceColor; + await TestEnvironment.cleanUp(testEnvironment); + }); + + describe("Data Sets", () => { + let dsnPrefix: string; + + let goodDsNames: string[]; + let badDsNames: string[]; + + let pdsNames: string[]; + let pdsGoodMemNames: string[]; + let pdsBadMemNames: string[]; + + let searchOptions: ISearchOptions; + let expectedApiResponse: any; + + beforeAll(async () => { + dsnPrefix = getUniqueDatasetName(`${defaultSystem.zosmf.user}.ZOSFILES.SEARCH`); + pattern = dsnPrefix + ".*"; + + goodDsNames = [`${dsnPrefix}.SEQ1`, `${dsnPrefix}.SEQ4`, `${dsnPrefix}.SEQ5`]; + badDsNames = [`${dsnPrefix}.SEQ2`, `${dsnPrefix}.SEQ3`]; + + pdsNames = [`${dsnPrefix}.PDS1`, `${dsnPrefix}.PDS2`]; + pdsGoodMemNames = ["MEM2", "MEM3"]; + pdsBadMemNames = ["MEM1", "MEM4"]; + + for (const dsn of [...goodDsNames, ...badDsNames]) { + await Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, dsn); + if (goodDsNames.includes(dsn)) { + await Upload.bufferToDataSet(REAL_SESSION, Buffer.from(goodTestString), `${dsn}`); + } else { + await Upload.bufferToDataSet(REAL_SESSION, Buffer.from(badTestString), `${dsn}`); + } + } + + for (const dsn of pdsNames) { + await Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_PARTITIONED, dsn); + for (const memname of pdsGoodMemNames) { + await Upload.bufferToDataSet(REAL_SESSION, Buffer.from(goodTestString), `${dsn}(${memname})`); + } + for (const memname of pdsBadMemNames) { + await Upload.bufferToDataSet(REAL_SESSION, Buffer.from(badTestString), `${dsn}(${memname})`); + } + } + }); + + afterAll(async () => { + for (const dsn of [...goodDsNames, ...badDsNames, ...pdsNames]) { + await Delete.dataSet(REAL_SESSION, dsn); + } + }); + + beforeEach(() => { + searchOptions = { + pattern, + searchString, + getOptions: {}, + listOptions: {}, + mainframeSearch: undefined, + progressTask: undefined, + maxConcurrentRequests: undefined, + timeout: undefined + }; + + expectedApiResponse = [ + {dsn: `${dsnPrefix}.PDS1`, member: "MEM2", matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.PDS1`, member: "MEM3", matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.PDS2`, member: "MEM2", matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.PDS2`, member: "MEM3", matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.SEQ1`, matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.SEQ4`, matchList: [{line: 1, column: 39, contents: goodTestString}]}, + {dsn: `${dsnPrefix}.SEQ5`, matchList: [{line: 1, column: 39, contents: goodTestString}]}, + ]; + }); + + it("should search and find the correct data sets", async () => { + const response = await Search.dataSets(REAL_SESSION, searchOptions); + + expect(response.errorMessage).not.toBeDefined(); + expect(response.success).toBe(true); + expect(response.commandResponse).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.commandResponse).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + expect(response.apiResponse).toEqual(expectedApiResponse); + }); + + it("should perform an initial mainframe search if requested", async () => { + searchOptions.mainframeSearch = true; + const response = await Search.dataSets(REAL_SESSION, searchOptions); + + expect(response.errorMessage).not.toBeDefined(); + expect(response.success).toEqual(true); + expect(response.commandResponse).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.commandResponse).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should handle case sensitive searches 1", async () => { + searchOptions.caseSensitive = true; + const response = await Search.dataSets(REAL_SESSION, searchOptions); + + expect(response.errorMessage).not.toBeDefined(); + expect(response.success).toEqual(true); + expect(response.commandResponse).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.commandResponse).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should handle case sensitive searches 2", async () => { + searchOptions.searchString = "Zowe CLI".toLowerCase(); + searchOptions.caseSensitive = true; + const response = await Search.dataSets(REAL_SESSION, searchOptions); + + expect(response.errorMessage).not.toBeDefined(); + expect(response.success).toEqual(true); + expect(response.commandResponse).toContain(`Found "${searchString.toLowerCase()}" in 0 data sets and PDS members`); + expect(response.commandResponse).not.toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.commandResponse).not.toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.commandResponse).not.toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.commandResponse).not.toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.commandResponse).not.toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.commandResponse).not.toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.commandResponse).not.toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.commandResponse).not.toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should allow for multiple concurrent requests", async () => { + searchOptions.maxConcurrentRequests = 2; + const response = await Search.dataSets(REAL_SESSION, searchOptions); + + expect(response.errorMessage).not.toBeDefined(); + expect(response.success).toEqual(true); + expect(response.commandResponse).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.commandResponse).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should time out after some time 1", async () => { + searchOptions.timeout = 120; + const response = await Search.dataSets(REAL_SESSION, searchOptions); + + expect(response.errorMessage).not.toBeDefined(); + expect(response.success).toEqual(true); + expect(response.commandResponse).toContain(`Found "${searchString}" in 7 data sets and PDS members`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM2":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS1" | Member "MEM3":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM2":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.PDS2" | Member "MEM3":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ1":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ4":`); + expect(response.commandResponse).toContain(`Data Set "${dsnPrefix}.SEQ5":`); + expect(response.commandResponse).toContain(`Line: 1, Column: 39, Contents: ${goodTestString}`); + }); + + it("should time out after some time 2", async () => { + searchOptions.timeout = 1; + const response = await Search.dataSets(REAL_SESSION, searchOptions); + + /** + * Since this test is timeout based, we cannot make many assumptions about what will or will not be found. + * The safest assumption is that something may or may not be found, but we will not find everything + * in under one second. + */ + expect(response.success).toEqual(false); + expect(response.commandResponse).toContain(`Found "${searchString}" in`); + expect(response.commandResponse).toContain(`data sets and PDS members`); + expect(response.errorMessage).toContain("The following data set(s) failed to be searched:"); + }); + + it("should fail without a pattern to search for", async () => { + searchOptions.pattern = undefined; + let error: any; + let response: IZosFilesResponse; + + try { + response = await Search.dataSets(REAL_SESSION, searchOptions); + } catch (err) { + error = err; + } + + expect(error).toBeDefined(); + expect(error.message).toContain("Required object must be defined"); + expect(response).not.toBeDefined(); + }); + + it("should fail without a query string to search for", async () => { + searchOptions.searchString = undefined; + let error: any; + let response: IZosFilesResponse; + + try { + response = await Search.dataSets(REAL_SESSION, searchOptions); + } catch (err) { + error = err; + } + + expect(error).toBeDefined(); + expect(error.message).toContain("Required object must be defined"); + expect(response).not.toBeDefined(); + }); + }); +}); \ No newline at end of file diff --git a/packages/zosfiles/__tests__/__unit__/methods/create/Create.unit.test.ts b/packages/zosfiles/__tests__/__unit__/methods/create/Create.unit.test.ts index 731bdc5004..3740bf2abf 100644 --- a/packages/zosfiles/__tests__/__unit__/methods/create/Create.unit.test.ts +++ b/packages/zosfiles/__tests__/__unit__/methods/create/Create.unit.test.ts @@ -10,7 +10,8 @@ */ import { ImperativeError, TextUtils } from "@zowe/imperative"; -import { Create, CreateDataSetTypeEnum, ZosFilesConstants, CreateDefaults, Invoke, ICreateVsamOptions, List } from "../../../../src"; +import { Create, CreateDataSetTypeEnum, ZosFilesConstants, CreateDefaults, Invoke, + ICreateVsamOptions, List, IZosFilesResponse } from "../../../../src"; import { ZosmfHeaders, ZosmfRestClient } from "@zowe/core-for-zowe-sdk"; import { ZosFilesMessages } from "../../../../src/constants/ZosFiles.messages"; import { IZosFilesOptions } from "../../../../src/doc/IZosFilesOptions"; @@ -29,7 +30,8 @@ describe("Create data set", () => { dsname: likePsDataSetName, dsorg: "PS", spacu: "TRK", - blksz: "800" + blksz: "800", + dsntype: "BASIC" }; beforeEach(() => { @@ -170,9 +172,13 @@ describe("Create data set", () => { dsOptions.dsntype = "PDS"; dsOptions.responseTimeout = 5; + let response: IZosFilesResponse; - const response = await Create.dataSet(dummySession, CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, dataSetName, dsOptions); - + try { + response = await Create.dataSet(dummySession, CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, dataSetName, dsOptions); + } finally { + dsOptions.responseTimeout = undefined; // This was messing up other tests if the code was not hit + } expect(response.success).toBe(true); expect(response.commandResponse).toContain("created successfully"); expect(mySpy).toHaveBeenCalledWith( @@ -183,11 +189,11 @@ describe("Create data set", () => { ...CreateDefaults.DATA_SET.SEQUENTIAL, ...dsOptions, ...{ + responseTimeout: 5, // Therefore this is required, because it is no longer in dsOptions secondary: 1 } }) ); - dsOptions.responseTimeout = undefined; }); it("should be able to allocate like from a sequential data set", async () => { @@ -232,8 +238,12 @@ describe("Create data set", () => { }; }); - const response2 = await Create.dataSetLike(dummySession, dataSetName, likePsDataSetName, dsOptions); - + let response2: IZosFilesResponse; + try { + response2 = await Create.dataSetLike(dummySession, dataSetName, likePsDataSetName, dsOptions); + } finally { + dsOptions.responseTimeout = undefined; + } expect(response2.success).toBe(true); expect(response2.commandResponse).toContain("created successfully"); expect(mySpy).toHaveBeenCalledWith( @@ -248,7 +258,6 @@ describe("Create data set", () => { } }) ); - dsOptions.responseTimeout = undefined; }); it("should be able to create a sequential data set using the primary allocation and secondary allocation options", async () => { @@ -806,7 +815,7 @@ describe("Create data set", () => { ); }); - it("should be able to create a partinioned data set without specifying an options object", async () => { + it("should be able to create a partitioned data set without specifying an options object", async () => { const response = await Create.dataSet(dummySession, CreateDataSetTypeEnum.DATA_SET_PARTITIONED, dataSetName); expect(response.success).toBe(true); @@ -823,7 +832,7 @@ describe("Create data set", () => { ); }); - it("should be able to create a partinioned data set without printing the attributes", async () => { + it("should be able to create a partitioned data set without printing the attributes", async () => { const response = await Create.dataSet( dummySession, CreateDataSetTypeEnum.DATA_SET_PARTITIONED, @@ -849,7 +858,7 @@ describe("Create data set", () => { ); }); - it("should be able to create a partinioned data set and print all the attributes", async () => { + it("should be able to create a partitioned data set and print all the attributes", async () => { const response = await Create.dataSet( dummySession, CreateDataSetTypeEnum.DATA_SET_PARTITIONED, @@ -997,7 +1006,7 @@ describe("Create data set", () => { it("should fail if passed an unexpected command type", async () => { let error; try { - await Create.dataSet(dummySession, -1, dataSetName, dsOptions); + await Create.dataSet(dummySession, -1 as CreateDataSetTypeEnum, dataSetName, dsOptions); } catch (err) { error = err.message; } @@ -1066,14 +1075,14 @@ describe("Create data set Validator", () => { expect(testOptions.secondary).toEqual(0); // Should be changed during create validation to zOSMF default of 0 }); - it("recfm should default to 'F' if not specified", async () => { + it("recfm should not default to anything if not specified", async () => { const testOptions: any = { recfm: undefined }; Create.dataSetValidateOptions(testOptions); - expect(testOptions.recfm).toEqual("F"); // Should be changed during create validation to zOSMF default of 'F' + expect(testOptions.recfm).not.toEqual("F"); // Should not be changed during create validation to zOSMF default of 'F' }); }); @@ -1316,8 +1325,8 @@ describe("Create VSAM Data Set", () => { `\nVOLUMES(STG100) -\n)`]; const options: IZosFilesOptions = {responseTimeout: undefined}; - dsOptions.showAttributes = true; dsOptions.volumes = "STG100"; + dsOptions.showAttributes = true; const response = await Create.vsam(dummySession, dataSetName, dsOptions); @@ -1334,9 +1343,9 @@ describe("Create VSAM Data Set", () => { const options: IZosFilesOptions = {responseTimeout: undefined}; dsOptions.primary = THIRTY; - dsOptions.showAttributes = false; dsOptions.alcunit = "TRK"; dsOptions.volumes = "STG100"; + dsOptions.showAttributes = false; const response = await Create.vsam(dummySession, dataSetName, dsOptions); diff --git a/packages/zosfiles/__tests__/__unit__/methods/download/Download.unit.test.ts b/packages/zosfiles/__tests__/__unit__/methods/download/Download.unit.test.ts index a7648237dc..9d7af8b881 100644 --- a/packages/zosfiles/__tests__/__unit__/methods/download/Download.unit.test.ts +++ b/packages/zosfiles/__tests__/__unit__/methods/download/Download.unit.test.ts @@ -15,7 +15,6 @@ import { ImperativeError, IO, Session } from "@zowe/imperative"; import { IDownloadOptions, TransferMode, Utilities, ZosFilesAttributes, ZosFilesMessages } from "../../../../src"; import { ZosmfHeaders, ZosmfRestClient } from "@zowe/core-for-zowe-sdk"; import { Download } from "../../../../src/methods/download/Download"; -import { posix, join } from "path"; import { ZosFilesConstants } from "../../../../src/constants/ZosFiles.constants"; import * as util from "util"; import { IUSSListOptions, List } from "../../../../src/methods/list"; @@ -124,7 +123,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, `-(${volume})`, dsname); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, `-(${volume})`, dsname); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -160,7 +159,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, `-(${volume})`, dsname); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, `-(${volume})`, dsname); const newDsContent = IO.processNewlines(dsContent.toString()); expect(caughtError).toBeUndefined(); @@ -195,7 +194,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -231,7 +230,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -269,7 +268,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -306,7 +305,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -342,7 +341,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -379,7 +378,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -413,7 +412,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -450,7 +449,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -487,7 +486,7 @@ describe("z/OS Files - Download", () => { } catch (e) { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, `-(${volume})`, dsname); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, `-(${volume})`, dsname); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -529,7 +528,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); expect(response).toBeUndefined(); expect(caughtError).toEqual(dummyError); @@ -554,7 +553,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -573,6 +572,38 @@ describe("z/OS Files - Download", () => { expect(ioCreateDirSpy).not.toHaveBeenCalled(); expect(ioWriteStreamSpy).not.toHaveBeenCalled(); }); + + it("should download a data set with additional query parameters", async () => { + let response; + let caughtError; + const destination = dsFolder + ".txt"; + + try { + response = await Download.dataSet(dummySession, dsname, { queryParams: "?test=true" }); + } catch (e) { + caughtError = e; + } + + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_DS_FILES, dsname + "?test=true"); + + expect(caughtError).toBeUndefined(); + expect(response).toEqual({ + success: true, + commandResponse: util.format(ZosFilesMessages.datasetDownloadedWithDestination.message, destination), + apiResponse: {} + }); + + expect(zosmfGetFullSpy).toHaveBeenCalledTimes(1); + expect(zosmfGetFullSpy).toHaveBeenCalledWith(dummySession, {resource: endpoint, + reqHeaders: [ZosmfHeaders.ACCEPT_ENCODING, ZosmfHeaders.TEXT_PLAIN], + responseStream: fakeWriteStream, + normalizeResponseNewLines: true, + task: undefined}); + + expect(ioCreateDirSpy).toHaveBeenCalledTimes(1); + expect(ioCreateDirSpy).toHaveBeenCalledWith(destination); + expect(ioWriteStreamSpy).toHaveBeenCalledTimes(1); + }); }); describe("allMembers", () => { @@ -684,7 +715,7 @@ describe("z/OS Files - Download", () => { expect(downloadDatasetSpy).toHaveBeenCalledTimes(2); listApiResponse.items.forEach((mem) => { expect(downloadDatasetSpy).toHaveBeenCalledWith(dummySession, `${dsname}(${mem.member})`, { - file: `${dsFolder}/${mem.member.toLowerCase()}.txt` + file: path.posix.join(dsFolder, mem.member.toLowerCase() + ".txt") }); }); }); @@ -718,7 +749,7 @@ describe("z/OS Files - Download", () => { listApiResponse.items.forEach((mem) => { expect(downloadDatasetSpy).toHaveBeenCalledWith(dummySession, `${dsname}(${mem.member})`, { volume, - file: `${directory}/${mem.member.toLowerCase()}${extension}`, + file: path.posix.join(directory, mem.member.toLowerCase() + extension), binary }); }); @@ -753,7 +784,7 @@ describe("z/OS Files - Download", () => { listApiResponse.items.forEach((mem) => { expect(downloadDatasetSpy).toHaveBeenCalledWith(dummySession, `${dsname}(${mem.member})`, { volume, - file: `${directory}/${mem.member.toLowerCase()}${extension}`, + file: path.posix.join(directory, mem.member.toLowerCase() + extension), record }); }); @@ -789,7 +820,7 @@ describe("z/OS Files - Download", () => { listApiResponse.items.forEach((mem) => { expect(downloadDatasetSpy).toHaveBeenCalledWith(dummySession, `${dsname}(${mem.member})`, { volume, - file: `${directory}/${mem.member.toLowerCase()}${extension}`, + file: path.posix.join(directory, mem.member.toLowerCase() + extension), binary, encoding: undefined, responseTimeout @@ -827,7 +858,7 @@ describe("z/OS Files - Download", () => { listApiResponse.items.forEach((mem) => { expect(downloadDatasetSpy).toHaveBeenCalledWith(dummySession, `${dsname}(${mem.member})`, { volume, - file: `${directory}/${mem.member.toLowerCase()}${extension}`, + file: path.posix.join(directory, mem.member.toLowerCase() + extension), record, encoding: undefined, responseTimeout @@ -864,7 +895,7 @@ describe("z/OS Files - Download", () => { listApiResponse.items.forEach((mem) => { expect(downloadDatasetSpy).toHaveBeenCalledWith(dummySession, `${dsname}(${mem.member})`, { volume, - file: `${directory}/${mem.member.toLowerCase()}${extension}`, + file: path.posix.join(directory, mem.member.toLowerCase() + extension), encoding }); }); @@ -898,7 +929,7 @@ describe("z/OS Files - Download", () => { listApiResponse.items.forEach((mem) => { expect(downloadDatasetSpy).toHaveBeenCalledWith(dummySession, `${dsname}(${mem.member})`, { volume, - file: `${directory}/${mem.member.toLowerCase()}${extension}` + file: path.posix.join(directory, mem.member.toLowerCase() + extension) }); }); }); @@ -932,7 +963,7 @@ describe("z/OS Files - Download", () => { listApiResponse.items.forEach((mem) => { expect(downloadDatasetSpy).toHaveBeenCalledWith(dummySession, `${dsname}(${mem.member})`, { volume, - file: `${directory}/${mem.member.toLowerCase()}${extension}`, + file: path.posix.join(directory, mem.member.toLowerCase() + extension), binary }); }); @@ -961,7 +992,7 @@ describe("z/OS Files - Download", () => { expect(downloadDatasetSpy).toHaveBeenCalledTimes(2); listApiResponse.items.forEach((mem) => { expect(downloadDatasetSpy).toHaveBeenCalledWith(dummySession, `${dsname}(${mem.member})`, { - file: `${dsFolder.toUpperCase()}/${mem.member}.txt` + file: path.posix.join(dsFolder.toUpperCase(), mem.member + ".txt") }); }); }); @@ -1014,7 +1045,7 @@ describe("z/OS Files - Download", () => { expect(downloadDatasetSpy).toHaveBeenCalledTimes(1); const firstItem = listApiResponse.items[0]; expect(downloadDatasetSpy).toHaveBeenCalledWith(dummySession, `${dsname}(${firstItem.member})`, { - file: `${dsFolder}/${firstItem.member.toLowerCase()}.txt` + file: path.posix.join(dsFolder, firstItem.member.toLowerCase() + ".txt") }); }); @@ -1046,10 +1077,10 @@ describe("z/OS Files - Download", () => { expect(downloadDatasetSpy).toHaveBeenCalledTimes(2); expect(downloadDatasetSpy).toHaveBeenCalledWith(dummySession, `${dsname}(${firstItem.member})`, { - file: `${dsFolder}/${firstItem.member.toLowerCase()}.txt` + file: path.posix.join(dsFolder, firstItem.member.toLowerCase() + ".txt") }); expect(downloadDatasetSpy).toHaveBeenCalledWith(dummySession, `${dsname}(${secondItem.member})`, { - file: `${dsFolder}/${secondItem.member.toLowerCase()}.txt` + file: path.posix.join(dsFolder, secondItem.member.toLowerCase() + ".txt") }); }); }); @@ -1844,7 +1875,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -1878,7 +1909,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -1916,7 +1947,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -1954,7 +1985,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -1995,7 +2026,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -2031,7 +2062,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -2064,7 +2095,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -2100,7 +2131,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -2134,7 +2165,7 @@ describe("z/OS Files - Download", () => { caughtError = e; } - const endpoint = posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, encodeURIComponent(ussname.substring(1))); expect(caughtError).toBeUndefined(); expect(response).toEqual({ @@ -2203,7 +2234,7 @@ describe("z/OS Files - Download", () => { expect(downloadUssFileSpy).toHaveBeenCalledTimes(1); expect(downloadUssFileSpy).toHaveBeenCalledWith(dummySession, ussDirName + "/file1", { - file: join(process.cwd(), "file1") + file: path.join(process.cwd(), "file1") }); }); @@ -2235,7 +2266,7 @@ describe("z/OS Files - Download", () => { expect(caughtError.causeErrors).toEqual(dummyError); expect(mkdirPromiseSpy).toHaveBeenCalledTimes(1); - expect(mkdirPromiseSpy).toHaveBeenCalledWith(join(process.cwd(), "folder1"), { recursive: true }); + expect(mkdirPromiseSpy).toHaveBeenCalledWith(path.join(process.cwd(), "folder1"), { recursive: true }); }); it("should download USS directory with download and list options", async () => { @@ -2271,7 +2302,7 @@ describe("z/OS Files - Download", () => { expect(List.fileList).toHaveBeenCalledWith(dummySession, ussDirName, { name: "*", ...listOptions }); expect(Download.ussFile).toHaveBeenCalledWith(dummySession, ussDirName + "/file1", - { file: join(process.cwd(), "file1"), ...fileOptions }); + { file: path.join(process.cwd(), "file1"), ...fileOptions }); }); it("should download USS directory when failFast is false", async () => { @@ -2344,7 +2375,7 @@ describe("z/OS Files - Download", () => { apiResponse: [fakeFileResponse] }); expect(Download.ussFile).toHaveBeenCalledWith(dummySession, ussDirName + "/file1", - { file: join(process.cwd(), "file1"), maxConcurrentRequests: 0 }); + { file: path.join(process.cwd(), "file1"), maxConcurrentRequests: 0 }); }); it("should download USS directory excluding hidden files", async () => { diff --git a/packages/zosfiles/__tests__/__unit__/methods/search/Search.unit.test.ts b/packages/zosfiles/__tests__/__unit__/methods/search/Search.unit.test.ts new file mode 100644 index 0000000000..62c1aea359 --- /dev/null +++ b/packages/zosfiles/__tests__/__unit__/methods/search/Search.unit.test.ts @@ -0,0 +1,1227 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ImperativeError, Session, TaskStage } from "@zowe/imperative"; +import { Get, ISearchItem, ISearchOptions, IZosFilesResponse, List, Search } from "../../../../src"; + +describe("Search", () => { + + const getDataSetSpy = jest.spyOn(Get, "dataSet"); + const dummySession = new Session({ + user: "ibmuser", + password: "ibmpass", + hostname: "ibmlpar", + port: 443, + protocol: "https", + type: "basic" + }); + + let testDataString = "THIS DATA SET CONTAINS SOME TESTDATA"; + let expectedCol = 29; + let expectedLine = 1; + + let searchOptions: ISearchOptions = { + pattern: "TEST*", + searchString: "TESTDATA", + caseSensitive: false, + getOptions: {}, + listOptions: {}, + mainframeSearch: true, + progressTask: undefined, + maxConcurrentRequests: 1, + timeout: undefined, + }; + let searchItems: ISearchItem[] = [ + {dsn: "TEST1.DS", member: undefined, matchList: undefined}, + {dsn: "TEST2.DS", member: undefined, matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: undefined} + ]; + let oldForceColor: string; + + function generateDS(name: string, pds: boolean, poe: boolean = false, migr: boolean = false) { + return { + dsname: name, + dsorg: pds ? poe ? "PO-E" : "PO" : "PS", + migr: migr ? "yes" : undefined + }; + } + function generateMembers(members: string[]) { + const mockItems = []; + for (const member of members) { + mockItems.push({member: member}); + } + return { + items: [ + ...mockItems + ] + }; + } + + beforeEach(() => { + expectedLine = 1; + expectedCol = 29; + testDataString = "THIS DATA SET CONTAINS SOME TESTDATA"; + + getDataSetSpy.mockClear(); + + getDataSetSpy.mockImplementation(async (session, dsn, options) => { + return Buffer.from(testDataString); + }); + + searchOptions = { + pattern: "TEST*", + searchString: "TESTDATA", + caseSensitive: false, + getOptions: {}, + listOptions: {}, + mainframeSearch: true, + progressTask: undefined, + maxConcurrentRequests: 1, + timeout: undefined, + }; + + searchItems = [ + {dsn: "TEST1.DS", member: undefined, matchList: undefined}, + {dsn: "TEST2.DS", member: undefined, matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: undefined} + ]; + + (Search as any).timerExpired = false; + }); + + beforeAll(() => { + // We can't test color related stuff in GitHub Actions + oldForceColor = process.env.FORCE_COLOR; + process.env.FORCE_COLOR = "0"; + }); + + afterAll(() => { + process.env.FORCE_COLOR = "0"; + jest.restoreAllMocks(); + }); + + describe("dataSets", () => { + const searchOnMainframeSpy = jest.spyOn(Search as any, "searchOnMainframe"); + const searchLocalSpy = jest.spyOn(Search as any, "searchLocal"); + const listDataSetsMatchingPatternSpy = jest.spyOn(List, "dataSetsMatchingPattern"); + const listAllMembersSpy = jest.spyOn(List, "allMembers"); + + function delay(ms: number) { jest.advanceTimersByTime(ms); } + function regenerateMockImplementations() { + searchOnMainframeSpy.mockImplementation(async (session, searchOptions, searchItems: ISearchItem[]) => { + if ((Search as any).timerExpired != true) { + return { + responses: searchItems, + failures: [] + }; + } else { + const failures: string[] = []; + for (const searchItem of searchItems) { + if (searchItem.member) { failures.push(searchItem.dsn + "(" + searchItem.member + ")"); } + else { failures.push(searchItem.dsn); } + } + return {responses: [], failures}; + } + }); + searchLocalSpy.mockImplementation(async (session, searchOptions, searchItems: ISearchItem[]) => { + if ((Search as any).timerExpired != true) { + const searchItemArray: ISearchItem[] = []; + for (const searchItem of searchItems) { + const localSearchItem: ISearchItem = searchItem; + localSearchItem.matchList = [{column: expectedCol, line: expectedLine, contents: testDataString}]; + searchItemArray.push(localSearchItem); + } + return {responses: searchItemArray, failures: []}; + } else { + const failures: string[] = []; + for (const searchItem of searchItems) { + if (searchItem.member) { failures.push(searchItem.dsn + "(" + searchItem.member + ")"); } + else { failures.push(searchItem.dsn); } + } + return {responses: [], failures}; + } + }); + listDataSetsMatchingPatternSpy.mockImplementation(async (session, patterns, options) => { + return { + success: true, + commandResponse: "", + apiResponse: [generateDS("TEST1.DS", false), generateDS("TEST2.DS", false), generateDS("TEST3.PDS", true)], + errorMessage: undefined + } as IZosFilesResponse; + }); + listAllMembersSpy.mockImplementation(async (session, dsn, options) => { + return { + success: true, + commandResponse: "", + apiResponse: generateMembers(["MEMBER1", "MEMBER2", "MEMBER3"]), + errorMessage: undefined + } as IZosFilesResponse; + }); + getDataSetSpy.mockImplementation(async (session, dsn, options) => { + return Buffer.from(testDataString); + }); + } + + beforeAll(() => { + jest.useFakeTimers(); + }); + + beforeEach(() => { + searchOnMainframeSpy.mockClear(); + searchLocalSpy.mockClear(); + listDataSetsMatchingPatternSpy.mockClear(); + listAllMembersSpy.mockClear(); + regenerateMockImplementations(); + }); + + afterAll(() => { + jest.useRealTimers(); + searchOnMainframeSpy.mockRestore(); + searchLocalSpy.mockRestore(); + }); + + it("Should search for the data sets containing a word", async () => { + const response = await Search.dataSets(dummySession, searchOptions); + + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledTimes(1); + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledWith(dummySession, ["TEST*"], {maxConcurrentRequests: 1}); + expect(listAllMembersSpy).toHaveBeenCalledTimes(1); + expect(listAllMembersSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS", {}); + expect(searchOnMainframeSpy).toHaveBeenCalledTimes(1); + expect(searchLocalSpy).toHaveBeenCalledTimes(1); + + expect(response.errorMessage).not.toBeDefined(); + expect(response.success).toEqual(true); + expect(response.apiResponse).toEqual([ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ]); + expect(response.commandResponse).toContain("Found \"TESTDATA\" in 5 data sets and PDS members"); + expect(response.commandResponse).toContain("Data Set \"TEST1.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST2.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER1\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER2\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER3\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + }); + + it("Should search for the data sets containing a word at the beginning of the string", async () => { + testDataString = "TESTDATA IS AT THE BEGINNING OF THE STRING"; + expectedCol = 1; + expectedLine = 1; + regenerateMockImplementations(); + const response = await Search.dataSets(dummySession, searchOptions); + + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledTimes(1); + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledWith(dummySession, ["TEST*"], {maxConcurrentRequests: 1}); + expect(listAllMembersSpy).toHaveBeenCalledTimes(1); + expect(listAllMembersSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS", {}); + expect(searchOnMainframeSpy).toHaveBeenCalledTimes(1); + expect(searchLocalSpy).toHaveBeenCalledTimes(1); + + expect(response.errorMessage).not.toBeDefined(); + expect(response.success).toEqual(true); + expect(response.apiResponse).toEqual([ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ]); + expect(response.commandResponse).toContain("Found \"TESTDATA\" in 5 data sets and PDS members"); + expect(response.commandResponse).toContain("Data Set \"TEST1.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST2.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER1\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER2\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER3\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + }); + + it("Should search for the data sets containing a word and sort out of order responses", async () => { + searchLocalSpy.mockImplementation(async (session, searchOptions, searchItems: ISearchItem[]) => { + const searchItemArray: ISearchItem[] = []; + for (const searchItem of searchItems) { + const localSearchItem: ISearchItem = searchItem; + localSearchItem.matchList = [{column: expectedCol, line: expectedLine, contents: testDataString}]; + searchItemArray.unshift(localSearchItem); + } + return {responses: searchItemArray, failures: []}; + }); + + const response = await Search.dataSets(dummySession, searchOptions); + + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledTimes(1); + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledWith(dummySession, ["TEST*"], {maxConcurrentRequests: 1}); + expect(listAllMembersSpy).toHaveBeenCalledTimes(1); + expect(listAllMembersSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS", {}); + expect(searchOnMainframeSpy).toHaveBeenCalledTimes(1); + expect(searchLocalSpy).toHaveBeenCalledTimes(1); + + expect(response.errorMessage).not.toBeDefined(); + expect(response.success).toEqual(true); + expect(response.apiResponse).toEqual([ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ]); + expect(response.commandResponse).toContain("Found \"TESTDATA\" in 5 data sets and PDS members"); + expect(response.commandResponse).toContain("Data Set \"TEST1.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST2.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER1\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER2\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER3\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + }); + + it("Should handle a migrated data set", async () => { + listDataSetsMatchingPatternSpy.mockImplementation(async (session, patterns, options) => { + return { + success: true, + commandResponse: "", + apiResponse: [generateDS("TEST1.DS", false), generateDS("TEST2.DS", false), generateDS("TEST3.PDS", true, false, true)], + errorMessage: undefined + } as IZosFilesResponse; + }); + + const response = await Search.dataSets(dummySession, searchOptions); + + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledTimes(1); + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledWith(dummySession, ["TEST*"], {maxConcurrentRequests: 1}); + expect(listAllMembersSpy).toHaveBeenCalledTimes(0); + expect(searchOnMainframeSpy).toHaveBeenCalledTimes(1); + expect(searchLocalSpy).toHaveBeenCalledTimes(1); + + expect(response.errorMessage).not.toBeDefined(); + expect(response.success).toEqual(true); + expect(response.apiResponse).toEqual([ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ]); + expect(response.commandResponse).toContain("Found \"TESTDATA\" in 2 data sets and PDS members"); + expect(response.commandResponse).toContain("Data Set \"TEST1.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST2.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + }); + + it("Should handle a PO-E data set", async () => { + listDataSetsMatchingPatternSpy.mockImplementation(async (session, patterns, options) => { + return { + success: true, + commandResponse: "", + apiResponse: [generateDS("TEST1.DS", false), generateDS("TEST2.DS", false), generateDS("TEST3.PDS", true, true)], + errorMessage: undefined + } as IZosFilesResponse; + }); + + const response = await Search.dataSets(dummySession, searchOptions); + + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledTimes(1); + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledWith(dummySession, ["TEST*"], {maxConcurrentRequests: 1}); + expect(listAllMembersSpy).toHaveBeenCalledTimes(1); + expect(listAllMembersSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS", {}); + expect(searchOnMainframeSpy).toHaveBeenCalledTimes(1); + expect(searchLocalSpy).toHaveBeenCalledTimes(1); + + expect(response.errorMessage).not.toBeDefined(); + expect(response.success).toEqual(true); + expect(response.apiResponse).toEqual([ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ]); + expect(response.commandResponse).toContain("Found \"TESTDATA\" in 5 data sets and PDS members"); + expect(response.commandResponse).toContain("Data Set \"TEST1.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST2.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER1\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER2\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER3\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + }); + + it("Should update the progress task if provided 1", async () => { + searchOptions.progressTask = { + stageName: TaskStage.NOT_STARTED, + percentComplete: 0, + statusMessage: undefined + }; + const response = await Search.dataSets(dummySession, searchOptions); + + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledTimes(1); + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledWith(dummySession, ["TEST*"], {maxConcurrentRequests: 1}); + expect(listAllMembersSpy).toHaveBeenCalledTimes(1); + expect(listAllMembersSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS", {}); + expect(searchOnMainframeSpy).toHaveBeenCalledTimes(1); + expect(searchLocalSpy).toHaveBeenCalledTimes(1); + + expect(response.errorMessage).not.toBeDefined(); + expect(response.success).toEqual(true); + expect(response.apiResponse).toEqual([ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ]); + expect(response.commandResponse).toContain("Found \"TESTDATA\" in 5 data sets and PDS members"); + expect(response.commandResponse).toContain("Data Set \"TEST1.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST2.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER1\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER2\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER3\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + + expect(searchOptions.progressTask.stageName).toEqual(TaskStage.COMPLETE); + expect(searchOptions.progressTask.percentComplete).toEqual(100); + expect(searchOptions.progressTask.statusMessage).toEqual("Search complete"); + }); + + it("Should update the progress task if provided 2", async () => { + searchOptions.progressTask = { + stageName: TaskStage.NOT_STARTED, + percentComplete: 0, + statusMessage: undefined + }; + searchLocalSpy.mockImplementation(async (session, searchOptions, searchItems: ISearchItem[]) => { + const searchItemArray: ISearchItem[] = []; + for (const searchItem of searchItems) { + const localSearchItem: ISearchItem = searchItem; + localSearchItem.matchList = [{column: expectedCol, line: expectedLine, contents: testDataString}]; + searchItemArray.push(localSearchItem); + } + (Search as any).timerExpired = true; + return {responses: searchItemArray, failures: []}; + }); + + const response = await Search.dataSets(dummySession, searchOptions); + + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledTimes(1); + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledWith(dummySession, ["TEST*"], {maxConcurrentRequests: 1}); + expect(listAllMembersSpy).toHaveBeenCalledTimes(1); + expect(listAllMembersSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS", {}); + expect(searchOnMainframeSpy).toHaveBeenCalledTimes(1); + expect(searchLocalSpy).toHaveBeenCalledTimes(1); + + expect(response.errorMessage).not.toBeDefined(); + expect(response.success).toEqual(true); + expect(response.apiResponse).toEqual([ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ]); + expect(response.commandResponse).toContain("Found \"TESTDATA\" in 5 data sets and PDS members"); + expect(response.commandResponse).toContain("Data Set \"TEST1.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST2.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER1\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER2\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST3.PDS\" | Member \"MEMBER3\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + + expect(searchOptions.progressTask.stageName).toEqual(TaskStage.COMPLETE); + expect(searchOptions.progressTask.percentComplete).toEqual(100); + expect(searchOptions.progressTask.statusMessage).toEqual("Search complete"); + }); + + it("Should handle if a PDS list fails", async () => { + listAllMembersSpy.mockImplementation(async (session, dsn, options) => { + throw new ImperativeError({msg: "Something went terribly wrong"}); + }); + + const response = await Search.dataSets(dummySession, searchOptions); + + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledTimes(1); + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledWith(dummySession, ["TEST*"], {maxConcurrentRequests: 1}); + expect(listAllMembersSpy).toHaveBeenCalledTimes(1); + expect(listAllMembersSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS", {}); + expect(searchOnMainframeSpy).toHaveBeenCalledTimes(1); + expect(searchLocalSpy).toHaveBeenCalledTimes(1); + + expect(response.errorMessage).toEqual("The following data set(s) failed to be searched: \nTEST3.PDS\n"); + expect(response.success).toEqual(false); + expect(response.apiResponse).toEqual([ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ]); + expect(response.commandResponse).toContain("Found \"TESTDATA\" in 2 data sets and PDS members"); + expect(response.commandResponse).toContain("Data Set \"TEST1.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST2.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + }); + + it("Should handle if a PDS list is empty", async () => { + listAllMembersSpy.mockImplementation(async (session, dsn, options) => { + return { + success: true, + commandResponse: "", + apiResponse: generateMembers([]), + errorMessage: undefined + } as IZosFilesResponse; + }); + + const response = await Search.dataSets(dummySession, searchOptions); + + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledTimes(1); + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledWith(dummySession, ["TEST*"], {maxConcurrentRequests: 1}); + expect(listAllMembersSpy).toHaveBeenCalledTimes(1); + expect(listAllMembersSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS", {}); + expect(searchOnMainframeSpy).toHaveBeenCalledTimes(1); + expect(searchLocalSpy).toHaveBeenCalledTimes(1); + + expect(response.errorMessage).not.toBeDefined(); + expect(response.success).toEqual(true); + expect(response.apiResponse).toEqual([ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ]); + expect(response.commandResponse).toContain("Found \"TESTDATA\" in 2 data sets and PDS members"); + expect(response.commandResponse).toContain("Data Set \"TEST1.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + expect(response.commandResponse).toContain("Data Set \"TEST2.DS\":\nLine: " + + expectedLine + ", Column: " + expectedCol + ", Contents: " + testDataString); + }); + + it("Should handle if listing data sets returns nothing", async () => { + listDataSetsMatchingPatternSpy.mockImplementation(async (session, patterns, options) => { + return { + success: true, + commandResponse: "", + apiResponse: [], + errorMessage: undefined + } as IZosFilesResponse; + }); + + const response = await Search.dataSets(dummySession, searchOptions); + + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledTimes(1); + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledWith(dummySession, ["TEST*"], {maxConcurrentRequests: 1}); + expect(listAllMembersSpy).toHaveBeenCalledTimes(0); + expect(searchOnMainframeSpy).toHaveBeenCalledTimes(1); + expect(searchLocalSpy).toHaveBeenCalledTimes(1); + + expect(response.errorMessage).not.toBeDefined(); + expect(response.success).toEqual(true); + expect(response.apiResponse).toEqual([]); + expect(response.commandResponse).toEqual("Found \"TESTDATA\" in 0 data sets and PDS members."); + }); + + it("Should terminate if listing data sets fails", async () => { + const impErr = new ImperativeError({msg: "Something went terribly wrong"}); + listDataSetsMatchingPatternSpy.mockImplementation(async (session, patterns, options) => { + throw impErr; + }); + + let err: any; + try { + await Search.dataSets(dummySession, searchOptions); + } catch (error) { + err = error; + } + + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledTimes(1); + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledWith(dummySession, ["TEST*"], {maxConcurrentRequests: 1}); + expect(listAllMembersSpy).toHaveBeenCalledTimes(0); + expect(searchOnMainframeSpy).toHaveBeenCalledTimes(0); + expect(searchLocalSpy).toHaveBeenCalledTimes(0); + + expect(err.message).toEqual("Failed to get list of data sets to search"); + expect(err.causeErrors).toEqual(impErr); + }); + + it("Should handle timing out 1", async () => { + searchLocalSpy.mockImplementation(async (session, searchOptions, searchItems: ISearchItem[]) => { + delay(1100); + if ((Search as any).timerExpired != true) { + const searchItemArray: ISearchItem[] = []; + for (const searchItem of searchItems) { + const localSearchItem: ISearchItem = searchItem; + localSearchItem.matchList = [{column: expectedCol, line: expectedLine, contents: testDataString}]; + searchItemArray.push(localSearchItem); + } + return {responses: searchItemArray, failures: []}; + } else { + const failures: string[] = []; + for (const searchItem of searchItems) { + if (searchItem.member) { failures.push(searchItem.dsn + "(" + searchItem.member + ")"); } + else { failures.push(searchItem.dsn); } + } + return {responses: [], failures}; + } + }); + searchOptions.timeout = 1; + searchOptions.progressTask = { + stageName: TaskStage.NOT_STARTED, + percentComplete: 0, + statusMessage: undefined + }; + + const response = await Search.dataSets(dummySession, searchOptions); + + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledTimes(1); + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledWith(dummySession, ["TEST*"], {maxConcurrentRequests: 1}); + expect(listAllMembersSpy).toHaveBeenCalledTimes(1); + expect(listAllMembersSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS", {}); + expect(searchOnMainframeSpy).toHaveBeenCalledTimes(1); + expect(searchLocalSpy).toHaveBeenCalledTimes(1); + + expect(response.errorMessage).toEqual("The following data set(s) failed to be searched: " + + "\nTEST1.DS\nTEST2.DS\nTEST3.PDS(MEMBER1)\nTEST3.PDS(MEMBER2)\nTEST3.PDS(MEMBER3)\n"); + expect(response.success).toEqual(false); + expect(response.apiResponse).toEqual([]); + expect(response.commandResponse).toContain("Found \"TESTDATA\" in 0 data sets and PDS members"); + + expect(searchOptions.progressTask.percentComplete).toEqual(100); + expect(searchOptions.progressTask.stageName).toEqual(TaskStage.FAILED); + expect(searchOptions.progressTask.statusMessage).toEqual("Operation timed out"); + }); + + it("Should handle timing out 2", async () => { + searchOnMainframeSpy.mockImplementation(async (session, searchOptions, searchItems: ISearchItem[]) => { + delay(1100); + if ((Search as any).timerExpired != true) { + return { + responses: searchItems, + failures: [] + }; + } else { + const failures: string[] = []; + for (const searchItem of searchItems) { + if (searchItem.member) { failures.push(searchItem.dsn + "(" + searchItem.member + ")"); } + else { failures.push(searchItem.dsn); } + } + return {responses: [], failures}; + } + }); + searchOptions.timeout = 1; + searchOptions.progressTask = { + stageName: TaskStage.NOT_STARTED, + percentComplete: 0, + statusMessage: undefined + }; + + const response = await Search.dataSets(dummySession, searchOptions); + + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledTimes(1); + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledWith(dummySession, ["TEST*"], {maxConcurrentRequests: 1}); + expect(listAllMembersSpy).toHaveBeenCalledTimes(1); + expect(listAllMembersSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS", {}); + expect(searchOnMainframeSpy).toHaveBeenCalledTimes(1); + expect(searchLocalSpy).toHaveBeenCalledTimes(1); + + expect(response.errorMessage).toEqual("The following data set(s) failed to be searched: " + + "\nTEST1.DS\nTEST2.DS\nTEST3.PDS(MEMBER1)\nTEST3.PDS(MEMBER2)\nTEST3.PDS(MEMBER3)\n"); + expect(response.success).toEqual(false); + expect(response.apiResponse).toEqual([]); + expect(response.commandResponse).toContain("Found \"TESTDATA\" in 0 data sets and PDS members"); + + expect(searchOptions.progressTask.percentComplete).toEqual(100); + expect(searchOptions.progressTask.stageName).toEqual(TaskStage.FAILED); + expect(searchOptions.progressTask.statusMessage).toEqual("Operation timed out"); + }); + + it("Should handle timing out 3", async () => { + listAllMembersSpy.mockImplementation(async (session, dsn, options) => { + delay(1100); + return { + success: true, + commandResponse: "", + apiResponse: generateMembers(["MEMBER1", "MEMBER2", "MEMBER3"]), + errorMessage: undefined + } as IZosFilesResponse; + }); + searchOptions.timeout = 1; + searchOptions.progressTask = { + stageName: TaskStage.NOT_STARTED, + percentComplete: 0, + statusMessage: undefined + }; + + const response = await Search.dataSets(dummySession, searchOptions); + + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledTimes(1); + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledWith(dummySession, ["TEST*"], {maxConcurrentRequests: 1}); + expect(listAllMembersSpy).toHaveBeenCalledTimes(1); + expect(listAllMembersSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS", {}); + expect(searchOnMainframeSpy).toHaveBeenCalledTimes(1); + expect(searchLocalSpy).toHaveBeenCalledTimes(1); + + expect(response.errorMessage).toEqual("The following data set(s) failed to be searched: " + + "\nTEST1.DS\nTEST2.DS\nTEST3.PDS(MEMBER1)\nTEST3.PDS(MEMBER2)\nTEST3.PDS(MEMBER3)\n"); + expect(response.success).toEqual(false); + expect(response.apiResponse).toEqual([]); + expect(response.commandResponse).toContain("Found \"TESTDATA\" in 0 data sets and PDS members"); + + expect(searchOptions.progressTask.percentComplete).toEqual(100); + expect(searchOptions.progressTask.stageName).toEqual(TaskStage.FAILED); + expect(searchOptions.progressTask.statusMessage).toEqual("Operation timed out"); + }); + + it("Should handle timing out 4", async () => { + listDataSetsMatchingPatternSpy.mockImplementation(async (session, patterns, options) => { + delay(1100); + return { + success: true, + commandResponse: "", + apiResponse: [generateDS("TEST1.DS", false), generateDS("TEST2.DS", false), generateDS("TEST3.PDS", true)], + errorMessage: undefined + } as IZosFilesResponse; + }); + searchOptions.timeout = 1; + searchOptions.progressTask = { + stageName: TaskStage.NOT_STARTED, + percentComplete: 0, + statusMessage: undefined + }; + + const response = await Search.dataSets(dummySession, searchOptions); + + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledTimes(1); + expect(listDataSetsMatchingPatternSpy).toHaveBeenCalledWith(dummySession, ["TEST*"], {maxConcurrentRequests: 1}); + expect(listAllMembersSpy).toHaveBeenCalledTimes(1); + expect(listAllMembersSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS", {}); + expect(searchOnMainframeSpy).toHaveBeenCalledTimes(1); + expect(searchLocalSpy).toHaveBeenCalledTimes(1); + + expect(response.errorMessage).toEqual("The following data set(s) failed to be searched: " + + "\nTEST1.DS\nTEST2.DS\nTEST3.PDS(MEMBER1)\nTEST3.PDS(MEMBER2)\nTEST3.PDS(MEMBER3)\n"); + expect(response.success).toEqual(false); + expect(response.apiResponse).toEqual([]); + expect(response.commandResponse).toContain("Found \"TESTDATA\" in 0 data sets and PDS members"); + + expect(searchOptions.progressTask.percentComplete).toEqual(100); + expect(searchOptions.progressTask.stageName).toEqual(TaskStage.FAILED); + expect(searchOptions.progressTask.statusMessage).toEqual("Operation timed out"); + }); + }); + + describe("searchOnMainframe", () => { + it("Should return a list of members that contain the search term (all)", async () => { + const searchString = searchOptions.searchString.toLowerCase(); + const response = await (Search as any).searchOnMainframe(dummySession, searchOptions, searchItems); + const queryParams = "?search=" + searchString + "&maxreturnsize=1"; + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {queryParams}); + expect(response).toEqual({responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: undefined}, + {dsn: "TEST2.DS", member: undefined, matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: undefined} + ], failures: []}); + }); + + it("Should return a list of members that contain the search term (none)", async () => { + // Return empty buffers for all entries + getDataSetSpy.mockImplementation(async (session, dsn, options) => { + return Buffer.from(""); + }); + + const searchString = searchOptions.searchString.toLowerCase(); + const response = await (Search as any).searchOnMainframe(dummySession, searchOptions, searchItems); + const queryParams = "?search=" + searchString + "&maxreturnsize=1"; + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {queryParams}); + expect(response).toEqual({responses: [], failures: []}); + }); + + it("Should return a list of members that contain the search term (some)", async () => { + // Return empty buffers for the final 2 entries + getDataSetSpy.mockImplementation(async (session, dsn, options) => { + return Buffer.from(""); + }).mockImplementationOnce(async (session, dsn, options) => { + return Buffer.from(testDataString); + }).mockImplementationOnce(async (session, dsn, options) => { + return Buffer.from(testDataString); + }).mockImplementationOnce(async (session, dsn, options) => { + return Buffer.from(testDataString); + }); + + const searchString = searchOptions.searchString.toLowerCase(); + const response = await (Search as any).searchOnMainframe(dummySession, searchOptions, searchItems); + const queryParams = "?search=" + searchString + "&maxreturnsize=1"; + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {queryParams}); + expect(response).toEqual({responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: undefined}, + {dsn: "TEST2.DS", member: undefined, matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: undefined} + ], failures: []}); + }); + + it("Should return failures if the timer expired", async () => { + (Search as any).timerExpired = true; + + const response = await (Search as any).searchOnMainframe(dummySession, searchOptions, searchItems); + + expect(getDataSetSpy).toHaveBeenCalledTimes(0); + expect(response).toEqual({ + responses: [], + failures: ["TEST1.DS", "TEST2.DS", "TEST3.PDS(MEMBER1)", "TEST3.PDS(MEMBER2)", "TEST3.PDS(MEMBER3)"] + }); + }); + + it("Should handle a data set get failure", async () => { + getDataSetSpy.mockImplementation(async (session, dsn, options) => { + return Buffer.from(testDataString); + }).mockImplementationOnce(async (session, dsn, options) => { + return Buffer.from(testDataString); + }).mockImplementationOnce(async (session, dsn, options) => { + throw new ImperativeError({msg: "Failed to retrieve contents of data set"}); + }); + + const searchString = searchOptions.searchString.toLowerCase(); + const response = await (Search as any).searchOnMainframe(dummySession, searchOptions, searchItems); + const queryParams = "?search=" + searchString + "&maxreturnsize=1"; + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {queryParams}); + expect(response).toEqual({ + responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: undefined} + ], + failures: ["TEST2.DS"] + }); + }); + + it("Should update the progress task, if present", async () => { + searchOptions.progressTask = { + percentComplete: 0, + statusMessage: "Getting Ready to Start", + stageName: TaskStage.IN_PROGRESS + }; + const searchString = searchOptions.searchString.toLowerCase(); + const response = await (Search as any).searchOnMainframe(dummySession, searchOptions, searchItems); + const queryParams = "?search=" + searchString + "&maxreturnsize=1"; + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {queryParams}); + expect(response).toEqual({responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: undefined}, + {dsn: "TEST2.DS", member: undefined, matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: undefined} + ], failures: []}); + expect(searchOptions.progressTask.stageName).toEqual(TaskStage.IN_PROGRESS); + + // Because the 5th entry is the last, there will have been 4 completed tasks + expect(searchOptions.progressTask.statusMessage).toEqual("Initial mainframe search: 4 of 5 entries checked"); + expect(searchOptions.progressTask.percentComplete).toEqual(40); + }); + + it("Should handle case sensitivity", async () => { + searchOptions.caseSensitive = true; + const searchString = searchOptions.searchString; + const response = await (Search as any).searchOnMainframe(dummySession, searchOptions, searchItems); + const queryParams = "?search=" + searchString + "&maxreturnsize=1&insensitive=false"; + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {queryParams}); + expect(response).toEqual({responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: undefined}, + {dsn: "TEST2.DS", member: undefined, matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: undefined} + ], failures: []}); + }); + + it("Should handle multiple concurrent requests", async () => { + searchOptions.maxConcurrentRequests = 2; + const searchString = searchOptions.searchString.toLowerCase(); + const response = await (Search as any).searchOnMainframe(dummySession, searchOptions, searchItems); + const queryParams = "?search=" + searchString + "&maxreturnsize=1"; + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {queryParams}); + expect(response).toEqual({responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: undefined}, + {dsn: "TEST2.DS", member: undefined, matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: undefined} + ], failures: []}); + }); + + it("Should handle no concurrent requests passed in", async () => { + searchOptions.maxConcurrentRequests = undefined; + const searchString = searchOptions.searchString.toLowerCase(); + const response = await (Search as any).searchOnMainframe(dummySession, searchOptions, searchItems); + const queryParams = "?search=" + searchString + "&maxreturnsize=1"; + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {queryParams}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {queryParams}); + expect(response).toEqual({responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: undefined}, + {dsn: "TEST2.DS", member: undefined, matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: undefined}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: undefined} + ], failures: []}); + }); + + it("Should handle being passed an empty list of search entries", async () => { + const response = await (Search as any).searchOnMainframe(dummySession, searchOptions, []); + + expect(getDataSetSpy).toHaveBeenCalledTimes(0); + expect(response).toEqual({responses: [], failures: []}); + }); + }); + + describe("searchLocal", () => { + it("Should return a list of members that contain the search term (all)", async () => { + const response = await (Search as any).searchLocal(dummySession, searchOptions, searchItems); + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {}); + expect(response).toEqual({responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ], failures: []}); + }); + + it("Should return a list of members that contain the search term (all) at the beginning", async () => { + expectedCol = 1; + expectedLine = 1; + testDataString = "TESTDATA IS AT THE BEGINNING OF THE STRING"; + const response = await (Search as any).searchLocal(dummySession, searchOptions, searchItems); + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {}); + expect(response).toEqual({responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ], failures: []}); + }); + + it("Should return a list of members that contain the search term (none)", async () => { + // Return non-matching buffers for all entries + getDataSetSpy.mockImplementation(async (session, dsn, options) => { + return Buffer.from("This data set does not contain any test data."); + }); + + const response = await (Search as any).searchLocal(dummySession, searchOptions, searchItems); + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {}); + expect(response).toEqual({responses: [], failures: []}); + }); + + it("Should return a list of members that contain the search term (some)", async () => { + // Return empty buffers for the final 2 entries + getDataSetSpy.mockImplementation(async (session, dsn, options) => { + return Buffer.from(""); + }).mockImplementationOnce(async (session, dsn, options) => { + return Buffer.from(testDataString); + }).mockImplementationOnce(async (session, dsn, options) => { + return Buffer.from(testDataString); + }).mockImplementationOnce(async (session, dsn, options) => { + return Buffer.from(testDataString); + }); + + const response = await (Search as any).searchLocal(dummySession, searchOptions, searchItems); + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {}); + expect(response).toEqual({responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ], failures: []}); + }); + + it("Should return failures if the timer expired", async () => { + (Search as any).timerExpired = true; + + const response = await (Search as any).searchLocal(dummySession, searchOptions, searchItems); + + expect(getDataSetSpy).toHaveBeenCalledTimes(0); + expect(response).toEqual({ + responses: [], + failures: ["TEST1.DS", "TEST2.DS", "TEST3.PDS(MEMBER1)", "TEST3.PDS(MEMBER2)", "TEST3.PDS(MEMBER3)"] + }); + }); + + it("Should handle a data set get failure", async () => { + getDataSetSpy.mockImplementation(async (session, dsn, options) => { + return Buffer.from(testDataString); + }).mockImplementationOnce(async (session, dsn, options) => { + return Buffer.from(testDataString); + }).mockImplementationOnce(async (session, dsn, options) => { + throw new ImperativeError({msg: "Failed to retrieve contents of data set"}); + }); + + const response = await (Search as any).searchLocal(dummySession, searchOptions, searchItems); + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {}); + expect(response).toEqual({ + responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ], + failures: ["TEST2.DS"] + }); + }); + + it("Should update the progress task, if present 1", async () => { + searchOptions.progressTask = { + percentComplete: 0, + statusMessage: "Getting Ready to Start", + stageName: TaskStage.IN_PROGRESS + }; + searchOptions.mainframeSearch = false; + const response = await (Search as any).searchLocal(dummySession, searchOptions, searchItems); + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {}); + expect(response).toEqual({responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ], failures: []}); + expect(searchOptions.progressTask.stageName).toEqual(TaskStage.IN_PROGRESS); + + // Because the 5th entry is the last, there will have been 4 completed tasks + expect(searchOptions.progressTask.statusMessage).toEqual("Performing search: 4 of 5 entries checked"); + expect(searchOptions.progressTask.percentComplete).toEqual(80); + }); + + it("Should update the progress task, if present 2", async () => { + searchOptions.progressTask = { + percentComplete: 40, + statusMessage: "Initial mainframe search: 4 of 5 entries checked", + stageName: TaskStage.IN_PROGRESS + }; + const response = await (Search as any).searchLocal(dummySession, searchOptions, searchItems); + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {}); + expect(response).toEqual({responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ], failures: []}); + expect(searchOptions.progressTask.stageName).toEqual(TaskStage.IN_PROGRESS); + + // Because the 5th entry is the last, there will have been 4 completed tasks + expect(searchOptions.progressTask.statusMessage).toEqual("Performing search: 4 of 5 entries checked"); + expect(searchOptions.progressTask.percentComplete).toEqual(90); + }); + + it("Should handle case sensitivity 1", async () => { + searchOptions.caseSensitive = true; + // Return empty buffers for the final 2 entries + getDataSetSpy.mockImplementation(async (session, dsn, options) => { + return Buffer.from(testDataString.toLowerCase()); + }).mockImplementationOnce(async (session, dsn, options) => { + return Buffer.from(testDataString); + }).mockImplementationOnce(async (session, dsn, options) => { + return Buffer.from(testDataString); + }).mockImplementationOnce(async (session, dsn, options) => { + return Buffer.from(testDataString); + }); + + const response = await (Search as any).searchLocal(dummySession, searchOptions, searchItems); + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {}); + expect(response).toEqual({responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ], failures: []}); + }); + + it("Should handle case sensitivity 2", async () => { + searchOptions.caseSensitive = true; + const response = await (Search as any).searchLocal(dummySession, searchOptions, searchItems); + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {}); + expect(response).toEqual({responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ], failures: []}); + }); + + it("Should handle multiple concurrent requests", async () => { + searchOptions.maxConcurrentRequests = 2; + const response = await (Search as any).searchLocal(dummySession, searchOptions, searchItems); + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {}); + expect(response).toEqual({responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ], failures: []}); + }); + + it("Should handle no concurrent requests passed in", async () => { + searchOptions.maxConcurrentRequests = undefined; + const response = await (Search as any).searchLocal(dummySession, searchOptions, searchItems); + + expect(getDataSetSpy).toHaveBeenCalledTimes(5); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST1.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST2.DS", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER1)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER2)", {}); + expect(getDataSetSpy).toHaveBeenCalledWith(dummySession, "TEST3.PDS(MEMBER3)", {}); + expect(response).toEqual({responses: [ + {dsn: "TEST1.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST2.DS", member: undefined, matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER1", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER2", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]}, + {dsn: "TEST3.PDS", member: "MEMBER3", matchList: [{column: expectedCol, line: expectedLine, contents: testDataString}]} + ], failures: []}); + }); + + it("Should handle being passed an empty list of search entries", async () => { + const response = await (Search as any).searchLocal(dummySession, searchOptions, []); + + expect(getDataSetSpy).toHaveBeenCalledTimes(0); + expect(response).toEqual({responses: [], failures: []}); + }); + }); +}); diff --git a/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts b/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts index 997c622d9c..9f232a790e 100644 --- a/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts +++ b/packages/zosfiles/__tests__/__unit__/methods/upload/Upload.unit.test.ts @@ -14,7 +14,7 @@ jest.mock("fs"); import * as path from "path"; import * as fs from "fs"; -import { ImperativeError, IO, NextVerFeatures, Session, IHeaderContent } from "@zowe/imperative"; +import { ImperativeError, IO, Session, IHeaderContent } from "@zowe/imperative"; import { ZosmfHeaders, ZosmfRestClient } from "@zowe/core-for-zowe-sdk"; import { IZosFilesResponse } from "../../../../src/doc/IZosFilesResponse"; import { ZosFilesConstants } from "../../../../src/constants/ZosFiles.constants"; @@ -46,13 +46,6 @@ describe("z/OS Files - Upload", () => { let response: IZosFilesResponse; let error: any; - beforeEach(() => { - /* This avoids having to mock ImperativeConfig.envVariablePrefix. - * Unless the choice below is overridden, tests will use our legacy format for errors. - */ - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(false); - }); - describe("fileToDataset", () => { const dataSetSpy = jest.spyOn(Upload as any, "pathToDataSet"); const lstatSpy = jest.spyOn(fs, "lstat"); @@ -353,7 +346,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeDefined(); expect(error.message).toContain(ZosFilesMessages.missingDatasetName.message); }); - it("should return error that throw by the ZosmfRestClient", async () => { + it("should return error that is thrown by the ZosmfRestClient", async () => { const buffer: Buffer = Buffer.from("testing"); const testError = new ImperativeError({ msg: "test error" @@ -1556,8 +1549,12 @@ describe("z/OS Files - Upload", () => { }); describe("bufferToUssFile", () => { - const zosmfExpectSpy = jest.spyOn(ZosmfRestClient, "putExpectString"); - let USSresponse: string; + const zosmfExpectSpy = jest.spyOn(ZosmfRestClient, "putExpectFullResponse"); + const fakeResponseWithEtag = { + data: Buffer.from(dsName), + response: { headers: { etag: etagValue } } + }; + let USSresponse: IZosFilesResponse; beforeEach(() => { USSresponse = undefined; error = undefined; @@ -1576,7 +1573,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeDefined(); expect(error.message).toContain(ZosFilesMessages.missingUSSFileName.message); }); - it("should return error that throw by the ZosmfRestClient", async () => { + it("should return error that is thrown by the ZosmfRestClient", async () => { const testError = new ImperativeError({ msg: "test error" }); @@ -1593,7 +1590,7 @@ describe("z/OS Files - Upload", () => { expect(error).toBeDefined(); expect(error).toBe(testError); }); - it("should return error that thrown when the 'record' option is specified", async () => { + it("should return error that is thrown when the 'record' option is specified", async () => { const record = true; try { @@ -1621,7 +1618,7 @@ describe("z/OS Files - Upload", () => { expect(USSresponse).toBeDefined(); expect(zosmfExpectSpy).toHaveBeenCalledTimes(1); - expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, endpoint, headers, data); + expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, { reqHeaders: headers, resource: endpoint, writeData: data }); }); it("should return with proper response when upload USS file with responseTimeout", async () => { const data: Buffer = Buffer.from("testing"); @@ -1646,7 +1643,7 @@ describe("z/OS Files - Upload", () => { expect(USSresponse).toBeDefined(); expect(zosmfExpectSpy).toHaveBeenCalledTimes(1); - expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, endpoint, headers, data); + expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, { reqHeaders: headers, resource: endpoint, writeData: data }); }); it("should return with proper response when upload USS file in binary", async () => { const data: Buffer = Buffer.from("testing"); @@ -1663,7 +1660,7 @@ describe("z/OS Files - Upload", () => { expect(USSresponse).toBeDefined(); expect(zosmfExpectSpy).toHaveBeenCalledTimes(1); - expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, endpoint, headers, data); + expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, { reqHeaders: headers, resource: endpoint, writeData: data }); }); it("should return with proper response when upload USS file with Etag", async () => { const data: Buffer = Buffer.from("testing"); @@ -1684,7 +1681,28 @@ describe("z/OS Files - Upload", () => { expect(USSresponse).toBeDefined(); expect(zosmfExpectSpy).toHaveBeenCalledTimes(1); - expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, endpoint, headers, data); + expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, { reqHeaders: headers, resource: endpoint, writeData: data }); + }); + it("should return with proper response when upload USS file and request Etag back", async () => { + const data: Buffer = Buffer.from("testing"); + const endpoint = path.posix.join(ZosFilesConstants.RESOURCE, ZosFilesConstants.RES_USS_FILES, dsName); + const headers = [ZosmfHeaders.X_IBM_TEXT, ZosmfHeaders.TEXT_PLAIN, ZosmfHeaders.ACCEPT_ENCODING, ZosmfHeaders.X_IBM_RETURN_ETAG]; + zosmfExpectSpy.mockImplementationOnce(async () => fakeResponseWithEtag); + try { + USSresponse = await Upload.bufferToUssFile(dummySession, dsName, data, {returnEtag: true}); + } catch (err) { + error = err; + } + + expect(error).toBeUndefined(); + expect(USSresponse).toBeDefined(); + expect(USSresponse.success).toBeTruthy(); + expect(USSresponse.apiResponse.etag).toBeDefined(); + expect(USSresponse.apiResponse.etag).toEqual(etagValue); + + expect(zosmfExpectSpy).toHaveBeenCalledTimes(1); + expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, { reqHeaders: headers, resource: endpoint, writeData: data, + dataToReturn: [CLIENT_PROPERTY.response] }); }); it("should set local encoding if specified", async () => { const data: Buffer = Buffer.from("testing"); @@ -1704,7 +1722,7 @@ describe("z/OS Files - Upload", () => { expect(USSresponse).toBeDefined(); expect(zosmfExpectSpy).toHaveBeenCalledTimes(1); - expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, endpoint, headers, data); + expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, { reqHeaders: headers, resource: endpoint, writeData: data }); }); it("should normalize new lines when upload USS file", async () => { const data: Buffer = Buffer.from("testing\r\ntesting2"); @@ -1723,7 +1741,7 @@ describe("z/OS Files - Upload", () => { const normalizedData = ZosFilesUtils.normalizeNewline(data); expect(data.length).not.toBe(normalizedData.length); expect(zosmfExpectSpy).toHaveBeenCalledTimes(1); - expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, endpoint, headers, normalizedData); + expect(zosmfExpectSpy).toHaveBeenCalledWith(dummySession, { reqHeaders: headers, resource: endpoint, writeData: normalizedData }); }); }); @@ -2468,7 +2486,7 @@ describe("z/OS Files - Upload", () => { // ignoredfile isDirSpy.mockImplementation((dirPath: string) => { - return (dirPath.endsWith("dir")); + return dirPath.endsWith("dir"); }); getFileListWithFsSpy.mockImplementation((dirPath: any): any[] => { if (dirPath.endsWith("uploaddir")) { diff --git a/packages/zosfiles/__tests__/__unit__/utils/__snapshots__/ZosFilesUtils.unit.test.ts.snap b/packages/zosfiles/__tests__/__unit__/utils/__snapshots__/ZosFilesUtils.unit.test.ts.snap index 3dcce8f4cf..9e94d47dcb 100644 --- a/packages/zosfiles/__tests__/__unit__/utils/__snapshots__/ZosFilesUtils.unit.test.ts.snap +++ b/packages/zosfiles/__tests__/__unit__/utils/__snapshots__/ZosFilesUtils.unit.test.ts.snap @@ -50,9 +50,6 @@ Object { exports[`ZosFilesUtils CONSTANTS should check if constant files have the expected constants loaded 2`] = ` Object { - "allDataSetsArchived": Object { - "message": "All data sets matching the selected pattern(s) were archived.", - }, "amsCommandExecutedSuccessfully": Object { "message": "AMS command executed successfully.", }, @@ -128,10 +125,6 @@ Destination: %s", "datasetRecalledSuccessfully": Object { "message": "Data set recall requested.", }, - "datasetsDownloadedSuccessfully": Object { - "message": "Data sets matching pattern downloaded successfully. -Destination: %s", - }, "errorParsingAttributesFile": Object { "message": "Error parsing attributes file {{file}}: {{message}}", }, @@ -272,18 +265,12 @@ Destination: %s", "noDataSetsMatchingPattern": Object { "message": "There are no data sets that match the provided pattern(s).", }, - "noDataSetsMatchingPatternRemain": Object { - "message": "After filtering out the archived files and files that match the exclusion-parameters, no data sets matching the supported organization type remain.", - }, "noMembersFound": Object { "message": "No members found!", }, "nodeJsFsError": Object { "message": "Node.js File System API error", }, - "onlyEmptyPartitionedDataSets": Object { - "message": "Only empty partitioned data sets match the provided patterns.", - }, "pathIsNotDirectory": Object { "message": "%s is not a directory", }, diff --git a/packages/zosfiles/package.json b/packages/zosfiles/package.json index d1d0cb3be4..9c5c20c9f0 100644 --- a/packages/zosfiles/package.json +++ b/packages/zosfiles/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-files-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "description": "Zowe SDK to interact with files and data sets on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -46,16 +46,19 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "minimatch": "5.0.1" + "minimatch": "^9.0.5" }, "devDependencies": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1", - "@zowe/zos-uss-for-zowe-sdk": "7.29.2" + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528", + "@zowe/zos-uss-for-zowe-sdk": "8.0.0-next.202409111528" }, "peerDependencies": { - "@zowe/core-for-zowe-sdk": "^7.0.0", - "@zowe/imperative": "^5.0.0" + "@zowe/core-for-zowe-sdk": "^8.0.0-next", + "@zowe/imperative": "^8.0.0-next" + }, + "engines": { + "node": ">=18.12.0" } } diff --git a/packages/zosfiles/src/constants/ZosFiles.messages.ts b/packages/zosfiles/src/constants/ZosFiles.messages.ts index a6ad5b3e40..7c58177267 100644 --- a/packages/zosfiles/src/constants/ZosFiles.messages.ts +++ b/packages/zosfiles/src/constants/ZosFiles.messages.ts @@ -207,16 +207,6 @@ export const ZosFilesMessages: { [key: string]: IMessageDefinition } = { message: "USS File or directory deleted successfully." }, - /** - * Message indicating that the data sets matching pattern was downloaded successfully - * @type {IMessageDefinition} - * @deprecated - */ - // eslint-disable-next-line deprecation/deprecation - datasetsDownloadedSuccessfully: { - message: "Data sets matching pattern downloaded successfully.\nDestination: %s" - }, - /** * Message indicating that the data sets matching pattern were listed successfully * @type {IMessageDefinition} @@ -409,26 +399,6 @@ export const ZosFilesMessages: { [key: string]: IMessageDefinition } = { message: "No list of data sets to download was passed." }, - /** - * Message indicating that all data sets matching the provided patterns are archived. - * @type {IMessageDefinition} - * @deprecated - */ - // eslint-disable-next-line deprecation/deprecation - allDataSetsArchived: { - message: "All data sets matching the selected pattern(s) were archived." - }, - - /** - * Message indicating that no data sets remain to be downloaded after the excluded ones were filtered out. - * @type {IMessageDefinition} - * @deprecated - */ - // eslint-disable-next-line deprecation/deprecation - noDataSetsInList: { - message: "No data sets left after excluded pattern(s) were filtered out." - }, - /** * Message indicating that no data sets remain to be downloaded after the excluded ones were filtered out. * @type {IMessageDefinition} @@ -440,22 +410,9 @@ export const ZosFilesMessages: { [key: string]: IMessageDefinition } = { /** * Message indicating that no data sets remain to be downloaded after the excluded ones were filtered out. * @type {IMessageDefinition} - * @deprecated - */ - // eslint-disable-next-line deprecation/deprecation - noDataSetsMatchingPatternRemain: { - message: "After filtering out the archived files and files that match the exclusion-parameters, no data sets matching" + - " the supported organization type remain." - }, - - /** - * Message indicating that only empty partitioned data sets match the provided patterns - * @type {IMessageDefinition} - * @deprecated */ - // eslint-disable-next-line deprecation/deprecation - onlyEmptyPartitionedDataSets: { - message: "Only empty partitioned data sets match the provided patterns." + noDataSetsInList: { + message: "No data sets left after excluded pattern(s) were filtered out." }, /** diff --git a/packages/zosfiles/src/doc/IOptionsFullResponse.ts b/packages/zosfiles/src/doc/IOptionsFullResponse.ts index cbd8ace04e..a93f8d349a 100644 --- a/packages/zosfiles/src/doc/IOptionsFullResponse.ts +++ b/packages/zosfiles/src/doc/IOptionsFullResponse.ts @@ -15,6 +15,7 @@ import { CLIENT_PROPERTY } from "./types/ZosmfRestClientProperties"; /** * Interface to define input options for RestClient GET|POST|PUT|DELETE ExpectFullResponse methods * @export + * @deprecated - Use Imperative's IOptionsFullResponse instead * @interface IOptionsFullResponse */ export interface IOptionsFullResponse { diff --git a/packages/zosfiles/src/doc/IRestClientResponse.ts b/packages/zosfiles/src/doc/IRestClientResponse.ts index 31efe05774..207fab5ea5 100644 --- a/packages/zosfiles/src/doc/IRestClientResponse.ts +++ b/packages/zosfiles/src/doc/IRestClientResponse.ts @@ -15,6 +15,7 @@ import { Session, Logger } from "@zowe/imperative"; /** * Interface to map client's REST call response * @export + * @deprecated - Use Imperative's IRestClientResponse instead * @interface IRestClientResponse */ export interface IRestClientResponse { diff --git a/packages/zosfiles/src/index.ts b/packages/zosfiles/src/index.ts index acb9e09a5f..0f74955d11 100644 --- a/packages/zosfiles/src/index.ts +++ b/packages/zosfiles/src/index.ts @@ -36,13 +36,10 @@ export * from "./methods/list"; export * from "./methods/mount"; export * from "./methods/hRecall"; export * from "./methods/rename"; +export * from "./methods/search"; export * from "./methods/unmount"; export * from "./methods/upload"; export * from "./methods/utilities"; export * from "./utils/ZosFilesAttributes"; -export * from "./utils/ZosFilesUtils"; -export * from "./doc/IOptionsFullResponse"; -export * from "./doc/IRestClientResponse"; -export * from "./doc/IOptions"; -export * from "./doc/types/ZosmfRestClientProperties"; \ No newline at end of file +export * from "./utils/ZosFilesUtils"; \ No newline at end of file diff --git a/packages/zosfiles/src/methods/copy/Copy.ts b/packages/zosfiles/src/methods/copy/Copy.ts index 8dacc64bdb..2f29a329c0 100644 --- a/packages/zosfiles/src/methods/copy/Copy.ts +++ b/packages/zosfiles/src/methods/copy/Copy.ts @@ -10,7 +10,7 @@ */ import { AbstractSession, ImperativeError, ImperativeExpect, ITaskWithStatus, Logger, Headers, - TaskStage } from "@zowe/imperative"; + IHeaderContent, TaskStage } from "@zowe/imperative"; import { posix } from "path"; import { Create, CreateDataSetTypeEnum, ICreateDataSetOptions } from "../create"; @@ -18,7 +18,7 @@ import { Get } from "../get"; import { Upload } from "../upload"; import { List } from "../list"; import { IGetOptions } from "../get/doc/IGetOptions"; -import { ZosmfRestClient, ZosmfHeaders, IHeaderContent } from "@zowe/core-for-zowe-sdk"; +import { ZosmfRestClient, ZosmfHeaders } from "@zowe/core-for-zowe-sdk"; import { ZosFilesConstants } from "../../constants/ZosFiles.constants"; import { ZosFilesMessages } from "../../constants/ZosFiles.messages"; import { IZosFilesResponse } from "../../doc/IZosFilesResponse"; @@ -262,7 +262,7 @@ export class Copy { * Don't overwrite an existing dataset or member if overwrite is false */ if(overwriteTarget || !targetFound || - (targetMember != undefined && !targetMemberFound )){ + targetMember != undefined && !targetMemberFound ){ /** * Upload the source data to the target dataset */ @@ -304,7 +304,7 @@ export class Copy { storclass: targetOptions.targetStorageClass, mgntclass: targetOptions.targetManagementClass, dataclass: targetOptions.targetDataClass, - dirblk: parseInt(((dsInfo.dsorg == "PO" || dsInfo.dsorg == "POE" ) ? "10" : "0")) + dirblk: parseInt(dsInfo.dsorg == "PO" || dsInfo.dsorg == "POE" ? "10" : "0") })); } diff --git a/packages/zosfiles/src/methods/create/Create.ts b/packages/zosfiles/src/methods/create/Create.ts index c93b96509d..c22028ca7e 100644 --- a/packages/zosfiles/src/methods/create/Create.ts +++ b/packages/zosfiles/src/methods/create/Create.ts @@ -91,7 +91,7 @@ export class Create { const tPrimary = tempOptions.size.toString().match(/[0-9]+/g); if (!(tPrimary === null || tPrimary === undefined)) { - tempOptions.primary = +(tPrimary.join("")); + tempOptions.primary = +tPrimary.join(""); if (tempOptions.secondary === null || tempOptions.secondary === undefined) { const TEN_PERCENT = 0.10; @@ -153,7 +153,7 @@ export class Create { headers.push({[ZosmfHeaders.X_IBM_RESPONSE_TIMEOUT]: options.responseTimeout.toString()}); } - const tempOptions = JSON.parse(JSON.stringify({ like: likeDataSetName, ...(options || {}) })); + const tempOptions = JSON.parse(JSON.stringify({ like: likeDataSetName, ...options || {} })); Create.dataSetValidateOptions(tempOptions); /* @@ -234,20 +234,10 @@ export class Create { tempOptions.blksize = tempOptions.lrecl; } - if(tempOptions.blksize <= tempOptions.lrecl ){ + if(tempOptions.blksize <= tempOptions.lrecl ){ tempOptions.blksize = tempOptions.lrecl; - if(tempOptions.recfm === null || tempOptions.recfm === undefined){ - tempOptions.recfm = "FB"; - } - switch (tempOptions.recfm.toUpperCase()) { - case "V": - case "VB": - case "VBS": - case "VS": - tempOptions.blksize += 4; - break; - default: - break; + if (tempOptions.recfm && tempOptions.recfm.toUpperCase().startsWith("V")) { + tempOptions.blksize += 4; } } break; @@ -315,31 +305,8 @@ export class Create { break; case "recfm": - // zOSMF defaults to F if missing so mimic it's behavior - if (tempOptions.recfm === null || tempOptions.recfm === undefined) { - tempOptions.recfm = "F"; - } + // no validation - // F, V, or U are required; B, A, M, S, T or additional - // VBA works on mainframe but not via zOSMF - switch (tempOptions.recfm.toUpperCase()) { - case "D": - case "DB": - case "DBS": - case "DS": - case "F": - case "FB": - case "FBS": - case "FS": - case "V": - case "VB": - case "VBS": - case "VS": - case "U": - break; - default: - throw new ImperativeError({ msg: ZosFilesMessages.invalidRecfmOption.message + tempOptions.recfm }); - } break; // SMS class values @@ -720,7 +687,7 @@ export class Create { case "perms": { const maxPerm = 777; - if ((options.perms < 0) || (options.perms > maxPerm)) { + if (options.perms < 0 || options.perms > maxPerm) { throw new ImperativeError({ msg: ZosFilesMessages.invalidPermsOption.message + options.perms }); @@ -757,4 +724,4 @@ export class Create { } } // end for } -} +} \ No newline at end of file diff --git a/packages/zosfiles/src/methods/delete/Delete.ts b/packages/zosfiles/src/methods/delete/Delete.ts index 8184afbd36..21d7be526f 100644 --- a/packages/zosfiles/src/methods/delete/Delete.ts +++ b/packages/zosfiles/src/methods/delete/Delete.ts @@ -9,11 +9,11 @@ * */ -import { AbstractSession, ImperativeExpect, Logger } from "@zowe/imperative"; +import { AbstractSession, ImperativeExpect, Logger, IHeaderContent } from "@zowe/imperative"; import { posix } from "path"; -import { ZosmfRestClient, IHeaderContent, ZosmfHeaders } from "@zowe/core-for-zowe-sdk"; +import { ZosmfRestClient, ZosmfHeaders } from "@zowe/core-for-zowe-sdk"; import { ZosFilesConstants } from "../../constants/ZosFiles.constants"; import { ZosFilesMessages } from "../../constants/ZosFiles.messages"; import { IZosFilesResponse } from "../../doc/IZosFilesResponse"; diff --git a/packages/zosfiles/src/methods/download/Download.ts b/packages/zosfiles/src/methods/download/Download.ts index 135b76a3c4..5944f6b6ee 100644 --- a/packages/zosfiles/src/methods/download/Download.ts +++ b/packages/zosfiles/src/methods/download/Download.ts @@ -9,22 +9,21 @@ * */ -import { AbstractSession, Headers, ImperativeExpect, IO, Logger, TaskProgress, ImperativeError, TextUtils } from "@zowe/imperative"; +import { AbstractSession, Headers, ImperativeExpect, IO, Logger, TaskProgress, ImperativeError, + TextUtils, IHeaderContent, IOptionsFullResponse, IRestClientResponse } from "@zowe/imperative"; import { posix, join, relative } from "path"; import * as fs from "fs"; import * as util from "util"; -import { ZosmfRestClient, IHeaderContent, ZosmfHeaders, asyncPool } from "@zowe/core-for-zowe-sdk"; +import { ZosmfRestClient, ZosmfHeaders, asyncPool } from "@zowe/core-for-zowe-sdk"; import { ZosFilesConstants } from "../../constants/ZosFiles.constants"; import { ZosFilesMessages } from "../../constants/ZosFiles.messages"; import { IZosFilesResponse } from "../../doc/IZosFilesResponse"; import { ZosFilesUtils } from "../../utils/ZosFilesUtils"; import { List } from "../list/List"; import { IDownloadOptions, IDownloadSingleOptions } from "./doc/IDownloadOptions"; -import { IRestClientResponse } from "../../doc/IRestClientResponse"; import { CLIENT_PROPERTY } from "../../doc/types/ZosmfRestClientProperties"; -import { IOptionsFullResponse } from "../../doc/IOptionsFullResponse"; import { Utilities } from "../utilities"; import { IZosmfListResponse } from "../list/doc/IZosmfListResponse"; import { IDownloadDsmResult } from "./doc/IDownloadDsmResult"; @@ -93,6 +92,9 @@ export class Download { } endpoint = posix.join(endpoint, encodeURIComponent(dataSetName)); + if (options.queryParams) { + endpoint += options.queryParams; + } Logger.getAppLogger().debug(`Endpoint: ${endpoint}`); @@ -260,7 +262,7 @@ export class Download { const fileName = options.preserveOriginalLetterCase ? mem.member : mem.member.toLowerCase(); return this.dataSet(session, `${dataSetName}(${mem.member})`, { volume: options.volume, - file: baseDir + IO.FILE_DELIM + fileName + IO.normalizeExtension(extension), + file: posix.join(baseDir, fileName + IO.normalizeExtension(extension)), binary: options.binary, record: options.record, encoding: options.encoding, @@ -269,7 +271,7 @@ export class Download { downloadErrors.push(err); failedMembers.push(fileName); // Delete the file that could not be downloaded - IO.deleteFile(baseDir + IO.FILE_DELIM + fileName + IO.normalizeExtension(extension)); + IO.deleteFile(join(baseDir, fileName + IO.normalizeExtension(extension))); // If we should fail fast, rethrow error if (options.failFast || options.failFast === undefined) { throw err; @@ -663,7 +665,7 @@ export class Download { // For each item in the listing... for (const item of list) { - if (item.name === "." || item.name === ".." || item.name === "..." || (!fileOptions.includeHidden && /(^|\/)\./.test(item.name))) { + if (item.name === "." || item.name === ".." || item.name === "..." || !fileOptions.includeHidden && /(^|\/)\./.test(item.name)) { // If the name is ., .., ..., or a hidden file, ignore it. continue; } else if (item.mode.startsWith("-")) { diff --git a/packages/zosfiles/src/methods/download/doc/IDownloadOptions.ts b/packages/zosfiles/src/methods/download/doc/IDownloadOptions.ts index e0af3e945e..103c496d2b 100644 --- a/packages/zosfiles/src/methods/download/doc/IDownloadOptions.ts +++ b/packages/zosfiles/src/methods/download/doc/IDownloadOptions.ts @@ -67,14 +67,6 @@ export interface IDownloadSingleOptions extends IGetOptions { * This interface defines options for downloading multiple data sets or USS files */ export interface IDownloadOptions extends Omit { - /** - * Exclude data sets that match these DSLEVEL patterns. Any data sets that match - * this pattern will not be downloaded - * @example "ibmuser.**.jcl, ibmuser.rexa.*" - * @deprecated Use the `List.dataSetsMatchingPattern` API to match data sets and exclude patterns - */ - excludePatterns?: string[]; - /** * Map data set names that match your pattern to the desired extension * @example cpgm=c,asmpgm=asm diff --git a/packages/zosfiles/src/methods/get/doc/IGetOptions.ts b/packages/zosfiles/src/methods/get/doc/IGetOptions.ts index 50c16acfbc..b1b2df23c2 100644 --- a/packages/zosfiles/src/methods/get/doc/IGetOptions.ts +++ b/packages/zosfiles/src/methods/get/doc/IGetOptions.ts @@ -23,4 +23,11 @@ export interface IGetOptions extends IOptions { * @memberof IGetOptions */ range?: string; + + /** + * Optional query parameters + * @type {string} + * @memberof IGetOptions + */ + queryParams?: string } diff --git a/packages/zosfiles/src/methods/invoke/Invoke.ts b/packages/zosfiles/src/methods/invoke/Invoke.ts index 0cbfd1538c..eac6174a50 100644 --- a/packages/zosfiles/src/methods/invoke/Invoke.ts +++ b/packages/zosfiles/src/methods/invoke/Invoke.ts @@ -10,11 +10,11 @@ */ import * as fs from "fs"; -import { AbstractSession, Headers, ImperativeError, ImperativeExpect, Logger } from "@zowe/imperative"; +import { AbstractSession, Headers, ImperativeError, ImperativeExpect, Logger, IHeaderContent } from "@zowe/imperative"; import { posix } from "path"; import * as util from "util"; -import { IHeaderContent, ZosmfRestClient, ZosmfHeaders, getErrorContext } from "@zowe/core-for-zowe-sdk"; +import { ZosmfRestClient, ZosmfHeaders, getErrorContext } from "@zowe/core-for-zowe-sdk"; import { ZosFilesConstants } from "../../constants/ZosFiles.constants"; import { ZosFilesMessages } from "../../constants/ZosFiles.messages"; import { IZosFilesResponse } from "../../doc/IZosFilesResponse"; diff --git a/packages/zosfiles/src/methods/list/List.ts b/packages/zosfiles/src/methods/list/List.ts index 10d8a29da0..4046d6095f 100644 --- a/packages/zosfiles/src/methods/list/List.ts +++ b/packages/zosfiles/src/methods/list/List.ts @@ -419,7 +419,7 @@ export class List { } // Exclude names of data sets - for (const pattern of (options.excludePatterns || [])) { + for (const pattern of options.excludePatterns || []) { const response = await List.dataSet(session, pattern); response.apiResponse.items.forEach((dataSetObj: IZosmfListResponse) => { const responseIndex = zosmfResponses.findIndex(response => response.dsname === dataSetObj.dsname); diff --git a/packages/zosfiles/src/methods/mount/Mount.ts b/packages/zosfiles/src/methods/mount/Mount.ts index 1bc3acdbd5..cb88b27248 100644 --- a/packages/zosfiles/src/methods/mount/Mount.ts +++ b/packages/zosfiles/src/methods/mount/Mount.ts @@ -95,7 +95,7 @@ export class Mount { switch (option) { case "mode": - if ((options.mode !== "rdonly") && (options.mode !== "rdwr")) { + if (options.mode !== "rdonly" && options.mode !== "rdwr") { throw new ImperativeError({ msg: ZosFilesMessages.invalidMountModeOption.message + options.mode }); diff --git a/packages/zosfiles/src/methods/rename/Rename.ts b/packages/zosfiles/src/methods/rename/Rename.ts index 2c6d07ccc3..0e1be569a4 100644 --- a/packages/zosfiles/src/methods/rename/Rename.ts +++ b/packages/zosfiles/src/methods/rename/Rename.ts @@ -9,10 +9,10 @@ * */ -import { AbstractSession, ImperativeExpect, Logger, Headers } from "@zowe/imperative"; +import { AbstractSession, ImperativeExpect, Logger, Headers, IHeaderContent } from "@zowe/imperative"; import { posix } from "path"; -import { ZosmfRestClient, IHeaderContent, ZosmfHeaders } from "@zowe/core-for-zowe-sdk"; +import { ZosmfRestClient, ZosmfHeaders } from "@zowe/core-for-zowe-sdk"; import { ZosFilesConstants } from "../../constants/ZosFiles.constants"; import { ZosFilesMessages } from "../../constants/ZosFiles.messages"; import { IZosFilesResponse } from "../../doc/IZosFilesResponse"; diff --git a/packages/zosfiles/src/methods/search/Search.ts b/packages/zosfiles/src/methods/search/Search.ts new file mode 100644 index 0000000000..e56416d499 --- /dev/null +++ b/packages/zosfiles/src/methods/search/Search.ts @@ -0,0 +1,360 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { AbstractSession, TextUtils, ImperativeError, ImperativeExpect, TaskStage } from "@zowe/imperative"; + +import { List } from "../list"; +import { ISearchItem } from "./doc/ISearchItem"; +import { Get } from "../get"; +import { ISearchMatchLocation } from "./doc/ISearchMatchLocation"; +import { asyncPool } from "@zowe/core-for-zowe-sdk"; +import { ISearchOptions } from "./doc/ISearchOptions"; +import { IZosFilesResponse } from "../../doc/IZosFilesResponse"; + +// This interface isn't used outside of the private functions, so just keeping it here. +interface ISearchResponse { + responses: ISearchItem[], + failures: string[] +} + +/** + * This class holds helper functions that are used to list data sets and its members through the z/OS MF APIs + */ +export class Search { + + /* Flag for an expired timeout */ + private static timerExpired: boolean = false; + + /** + * Retrieve all data sets and members to search + * + * @param {AbstractSession} session - z/OS MF connection info + * @param {ISearchOptions} searchOptions - contains the data set search options, + * including name, searchString, timeout, and maxConcurrentRequests + * + * @returns {Promise} A response indicating the outcome of the API + * + * @throws {ImperativeError} data set name must be set + * @throws {Error} When the {@link ZosmfRestClient} throws an error + */ + + public static async dataSets(session: AbstractSession, searchOptions: ISearchOptions): Promise { + ImperativeExpect.toBeDefinedAndNonBlank(searchOptions.pattern, "pattern"); + ImperativeExpect.toBeDefinedAndNonBlank(searchOptions.searchString, "searchString"); + + const failedDatasets: string[] = []; + const origSearchQuery = searchOptions.searchString; + let timer: NodeJS.Timeout; + this.timerExpired = false; + + // Handle timeouts + if (searchOptions.timeout) { + timer = setTimeout(() => { + this.timerExpired = true; + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + }, searchOptions.timeout * 1000); + } + + // Handle progress bars + if (searchOptions.progressTask) { + searchOptions.progressTask.stageName = TaskStage.IN_PROGRESS; + searchOptions.progressTask.percentComplete = 0; + searchOptions.progressTask.statusMessage = "Getting search list..."; + } + + // List all data sets that match the search term + let searchItems: ISearchItem[] = []; + const partitionedDataSets: string[] = []; + + // We are in trouble if list fails - exit if it does + try { + const response = await List.dataSetsMatchingPattern(session, [searchOptions.pattern], { + ...searchOptions.listOptions, + maxConcurrentRequests: searchOptions.maxConcurrentRequests + }); + for (const resp of response.apiResponse) { + // Skip anything that doesn't have a DSORG or is migrated + if (resp.dsorg && !(resp.migr && resp.migr.toLowerCase() === "yes")) { + if (resp.dsorg === "PS") { // Sequential + searchItems.push({dsn: resp.dsname}); + } else if (resp.dsorg === "PO" || resp.dsorg === "PO-E") { // Partitioned + partitionedDataSets.push(resp.dsname); + } + } + } + } catch (err) { + throw new ImperativeError({msg: "Failed to get list of data sets to search", causeErrors: err}); + } + + // Get a list of members if a data set is a PDS + for (const pds of partitionedDataSets) { + try { + const response = await List.allMembers(session, pds, searchOptions.listOptions); + if (response.apiResponse.items.length > 0) { + for (const item of response.apiResponse.items) { + if (item.member != undefined) { searchItems.push({dsn: pds, member: item.member}); } + } + } + } catch (err) { + failedDatasets.push(pds); + } + } + + // Start searching on the mainframe if applicable + if (searchOptions.mainframeSearch) { + const response = await this.searchOnMainframe(session, searchOptions, searchItems); + searchItems = response.responses; + failedDatasets.push(...response.failures); + } + + // Start searching locally + const response = await this.searchLocal(session, searchOptions, searchItems); + const matchResponses = response.responses; + failedDatasets.push(...response.failures); + + if (searchOptions.progressTask) { + if (this.timerExpired && failedDatasets.length >= 1) { + searchOptions.progressTask.stageName = TaskStage.FAILED; + searchOptions.progressTask.percentComplete = 100; + searchOptions.progressTask.statusMessage = "Operation timed out"; + } else { + searchOptions.progressTask.stageName = TaskStage.COMPLETE; + searchOptions.progressTask.percentComplete = 100; + searchOptions.progressTask.statusMessage = "Search complete"; + } + } + + if (this.timerExpired) { this.timerExpired = false; } + if (timer) { + clearTimeout(timer); + } + + // Sort responses to make it pretty + matchResponses.sort((a, b) => { + const sort = a.dsn.localeCompare(b.dsn); + if (sort === 0) { + return a.member.localeCompare(b.member); + } else { + return sort; + } + }); + + const chalk = TextUtils.chalk; + + const apiResponse: IZosFilesResponse = { + success: failedDatasets.length <= 0, + commandResponse: "Found \"" + chalk.yellow(origSearchQuery) + "\" in " + + chalk.yellow(matchResponses.length) + " data sets and PDS members", + apiResponse: matchResponses + }; + + if (matchResponses.length >= 1) { + apiResponse.commandResponse += ":\n"; + for (const entry of matchResponses) { + apiResponse.commandResponse += "\n" + chalk.yellow("Data Set") + " \"" + entry.dsn + "\""; + + if (entry.member) { apiResponse.commandResponse += " | " + chalk.yellow("Member") + " \"" + entry.member + "\":\n"; } + else { apiResponse.commandResponse += ":\n"; } + + let maxLine: number = 0; + let maxCol: number = 0; + for (const {line, column} of entry.matchList) { + if (line > maxLine) { maxLine = line; } + if (column > maxCol) { maxCol = column; } + } + + const lineLen = maxLine.toString().length; + const colLen = maxCol.toString().length; + const searchLen = searchOptions.searchString.length; + + for (const {line, column, contents} of entry.matchList) { + // eslint-disable-next-line no-control-regex + let localContents = contents.replace(/[\u0000-\u001F\u007F-\u009F]/g, "\uFFFD"); + const beforeString = chalk.grey(localContents.substring(0, column - 1)); + const selectedString = chalk.white.bold(localContents.substring(column - 1, column - 1 + searchLen)); + const afterString = chalk.grey(localContents.substring(column - 1 + searchLen, localContents.length + 1)); + localContents = beforeString + selectedString + afterString; + apiResponse.commandResponse += chalk.yellow("Line:") + " " + line.toString().padStart(lineLen) + + ", " + chalk.yellow("Column:") + " " + column.toString().padStart(colLen) + ", " + chalk.yellow("Contents:") + + " " + localContents + "\n"; + } + } + } else { + apiResponse.commandResponse += "."; + } + + if (!apiResponse.success) { + apiResponse.errorMessage = "The following data set(s) failed to be searched: \n"; + for (const entry of failedDatasets) { apiResponse.errorMessage += entry + "\n"; } + } + + return apiResponse; + } + + /** + * Perform a prelimiary search on z/OSMF + * + * @param {AbstractSession} session - z/OS MF connection info + * @param {ISearchOptions} searchOptions - Search options + * @param {ISearchItem[]} searchItems - List of items for searching + * + * @returns {Promise} A list of members that contain the searched for term + * + * @throws {ImperativeError} when a download fails, or timeout is exceeded. + */ + private static async searchOnMainframe(session: AbstractSession, searchOptions: ISearchOptions, searchItems: ISearchItem[]): + Promise { + const matches: ISearchItem[] = []; + const failures: string[] = []; + const total = searchItems.length; + let complete = 0; + + const createSearchPromise = async (searchItem: ISearchItem) => { + if (!this.timerExpired) { + // Update the progress bar + if (searchOptions.progressTask) { + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + searchOptions.progressTask.percentComplete = Math.floor(complete / total / 2 * 100); + searchOptions.progressTask.statusMessage = "Initial mainframe search: " + complete + " of " + total + " entries checked"; + } + + // Handle case sensitivity + if (searchOptions.caseSensitive == undefined || searchOptions.caseSensitive === false) { + searchOptions.searchString = searchOptions.searchString.toLowerCase(); + } + + // Set up the query + let queryParams = "?search=" + encodeURIComponent(searchOptions.searchString) + "&maxreturnsize=1"; + if (searchOptions.caseSensitive === true) { queryParams += "&insensitive=false"; } + let dsn = searchItem.dsn; + if (searchItem.member) { dsn += "(" + searchItem.member + ")"; } + + // Get the response from the mainframe + let getResponseBuffer: Buffer; + try { + getResponseBuffer = await Get.dataSet(session, dsn, {...searchOptions.getOptions, queryParams}); + } catch (err) { + failures.push(dsn); + complete++; + return; + } + if (!(getResponseBuffer == null || getResponseBuffer.byteLength === 0)) { + matches.push(searchItem); + } + complete++; + } else { + if (searchItem.member) { + failures.push(searchItem.dsn + "(" + searchItem.member + ")"); + } else { + failures.push(searchItem.dsn); + } + complete++; + } + }; + + await asyncPool(searchOptions.maxConcurrentRequests || 1, searchItems, createSearchPromise); + return {responses: matches, failures}; + } + + /** + * Perform a deep search locally + * + * @param {AbstractSession} session - z/OS MF connection info + * @param {ISearchOptions} searchOptions - Search options + * + * @returns {Promise} A list of members that contain the searched for term, and locations where the term appears + * + * @throws {ImperativeError} when a download fails, or timeout is exceeded. + */ + private static async searchLocal(session: AbstractSession, searchOptions: ISearchOptions, searchItems: ISearchItem[]): Promise { + const matchedItems: ISearchItem[] = []; + const failures: string[] = []; + const total = searchItems.length; + let complete = 0; + const createFindPromise = async (searchItem: ISearchItem) => { + if (!this.timerExpired) { + // Handle the progress bars + if (searchOptions.progressTask) { + if (searchOptions.mainframeSearch) { + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + searchOptions.progressTask.percentComplete = Math.floor(complete / total / 2 * 100 + 50); + searchOptions.progressTask.statusMessage = "Performing search: " + complete + " of " + total + " entries checked"; + } else { + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + searchOptions.progressTask.percentComplete = Math.floor(complete / total * 100); + searchOptions.progressTask.statusMessage = "Performing search: " + complete + " of " + total + " entries checked"; + } + } + + // Set up the query + let dsn = searchItem.dsn; + if (searchItem.member) { dsn += "(" + searchItem.member + ")"; } + + // Get the item + let getResponseBuffer: Buffer; + try { + getResponseBuffer = await Get.dataSet(session, dsn, searchOptions.getOptions); + } catch (err) { + failures.push(dsn); + complete++; + return; + } + const getResponseString = getResponseBuffer.toString(); + const getResponseStringArray = getResponseString.split(/\r?\n/); + + // Handle case sensitivity + if (searchOptions.caseSensitive == undefined || searchOptions.caseSensitive === false) { + searchOptions.searchString = searchOptions.searchString.toLowerCase(); + } + + // Perform the search + const indicies: ISearchMatchLocation[] = []; + let lineNum = 0; + for (const line of getResponseStringArray) { + // Handle temporary storage of comparison data - we want the original to return to the caller + let searchLine = line; + if (searchOptions.caseSensitive == undefined || searchOptions.caseSensitive === false) { + searchLine = line.toLowerCase(); + } + + if (searchLine.includes(searchOptions.searchString)) { + let lastCol = 0; + let lastColIndexPlusLen = 0; + while (lastCol != -1) { + const column = searchLine.indexOf(searchOptions.searchString, lastColIndexPlusLen); + lastCol = column; + lastColIndexPlusLen = column + searchOptions.searchString.length; + if (column != -1) { + // Append the real line - 1 indexed + indicies.push({line: lineNum + 1, column: column + 1, contents: line}); + } + } + } + lineNum++; + } + if (indicies.length > 0) { + searchItem.matchList = indicies; + matchedItems.push(searchItem); + } + complete++; + } else { + if (searchItem.member) { + failures.push(searchItem.dsn + "(" + searchItem.member + ")"); + } else { + failures.push(searchItem.dsn); + } + complete++; + } + }; + await asyncPool(searchOptions.maxConcurrentRequests || 1, searchItems, createFindPromise); + return {responses: matchedItems, failures}; + } +} diff --git a/packages/zosfiles/src/methods/search/doc/ISearchItem.ts b/packages/zosfiles/src/methods/search/doc/ISearchItem.ts new file mode 100644 index 0000000000..f205975454 --- /dev/null +++ b/packages/zosfiles/src/methods/search/doc/ISearchItem.ts @@ -0,0 +1,23 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { IDataSet } from "../../../doc/IDataSet"; +import { ISearchMatchLocation } from "./ISearchMatchLocation"; + +/** + * This interface defines the information that is stored in the download data set API return object + */ +export interface ISearchItem extends IDataSet { + /** + * The short content of the member + */ + matchList?: ISearchMatchLocation[]; +} diff --git a/packages/imperative/src/profiles/src/doc/response/IProfileUpdated.ts b/packages/zosfiles/src/methods/search/doc/ISearchMatchLocation.ts similarity index 50% rename from packages/imperative/src/profiles/src/doc/response/IProfileUpdated.ts rename to packages/zosfiles/src/methods/search/doc/ISearchMatchLocation.ts index 59921265ef..d1e2a67766 100644 --- a/packages/imperative/src/profiles/src/doc/response/IProfileUpdated.ts +++ b/packages/zosfiles/src/methods/search/doc/ISearchMatchLocation.ts @@ -9,23 +9,22 @@ * */ -import { IProfile } from "../definition/IProfile"; /** - * The success response to the profile "update()" API. - * @export - * @interface IProfileUpdated + * This interface defines the information that is stored in the download data set API return object */ -export interface IProfileUpdated { +export interface ISearchMatchLocation { /** - * The path to the profile that was updated + * The line number that the match was found in */ - path: string; + line: number; + /** - * A message for display purposes + * The column number that the match was found in */ - message: string; + column: number; + /** - * The contents of the profile + * The contents of that line where the search term was found */ - profile?: IProfile; + contents: string; } diff --git a/packages/zosfiles/src/methods/search/doc/ISearchOptions.ts b/packages/zosfiles/src/methods/search/doc/ISearchOptions.ts new file mode 100644 index 0000000000..c7cb81578a --- /dev/null +++ b/packages/zosfiles/src/methods/search/doc/ISearchOptions.ts @@ -0,0 +1,43 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ITaskWithStatus } from "@zowe/imperative"; +import { IGetOptions } from "../../get"; +import { IListOptions } from "../../list"; + +export interface ISearchOptions { + /* The pattern matching the data set(s) that should be searched */ + pattern: string; + + /* The string to search for in the data set / members */ + searchString: string; + + /* Options for data set get requests */ + getOptions?: IGetOptions; + + /* Options for data set list requests */ + listOptions?: IListOptions; + + /* Should an initial search be done on the mainframe? */ + mainframeSearch?: boolean; + + /* A progress bar task if we want a progress bar */ + progressTask?: ITaskWithStatus; + + /* The number of concurrent requests to use to perform the search */ + maxConcurrentRequests?: number; + + /* The amount of time, in seconds, before a timeout should occur */ + timeout?: number; + + /* The search should be case sensitive */ + caseSensitive?: boolean; +} \ No newline at end of file diff --git a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_pluginHealthCheck/dummy.handler.js b/packages/zosfiles/src/methods/search/index.ts similarity index 68% rename from packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_pluginHealthCheck/dummy.handler.js rename to packages/zosfiles/src/methods/search/index.ts index fe821d5fd8..bec37537e0 100644 --- a/packages/imperative/__tests__/src/packages/imperative/plugins/test_plugins/error_plugins/missing_pluginHealthCheck/dummy.handler.js +++ b/packages/zosfiles/src/methods/search/index.ts @@ -9,6 +9,8 @@ * */ -/** - * Dummy handler should not be called - */ \ No newline at end of file +export * from "./doc/ISearchMatchLocation"; +export * from "./doc/ISearchItem"; +export * from "./doc/ISearchOptions"; + +export * from "./Search"; diff --git a/packages/zosfiles/src/methods/upload/Upload.ts b/packages/zosfiles/src/methods/upload/Upload.ts index 220c0c21bc..985cf0455c 100644 --- a/packages/zosfiles/src/methods/upload/Upload.ts +++ b/packages/zosfiles/src/methods/upload/Upload.ts @@ -9,11 +9,12 @@ * */ -import { AbstractSession, Headers, ImperativeError, ImperativeExpect, IO, Logger, TaskProgress } from "@zowe/imperative"; +import { AbstractSession, Headers, ImperativeError, ImperativeExpect, IO, Logger, + TaskProgress, IHeaderContent, IOptionsFullResponse, IRestClientResponse } from "@zowe/imperative"; import * as fs from "fs"; import * as path from "path"; -import { IHeaderContent, ZosmfHeaders, ZosmfRestClient, asyncPool } from "@zowe/core-for-zowe-sdk"; +import { ZosmfHeaders, ZosmfRestClient, asyncPool } from "@zowe/core-for-zowe-sdk"; import { ZosFilesConstants } from "../../constants/ZosFiles.constants"; import { ZosFilesMessages } from "../../constants/ZosFiles.messages"; @@ -27,8 +28,6 @@ import { IUploadFile } from "./doc/IUploadFile"; import { IUploadDir } from "./doc/IUploadDir"; import { Utilities, Tag } from "../utilities"; import { Readable } from "stream"; -import { IOptionsFullResponse } from "../../doc/IOptionsFullResponse"; -import { IRestClientResponse } from "../../doc/IRestClientResponse"; import { CLIENT_PROPERTY } from "../../doc/types/ZosmfRestClientProperties"; import { TransferMode } from "../../utils/ZosFilesAttributes"; @@ -447,26 +446,52 @@ export class Upload { * Upload content to USS file * @param {AbstractSession} session - z/OS connection info * @param {string} ussname - Name of the USS file to write to - * @param {Buffer} buffer - Data to be written + * @param {Buffer} fileBuffer - Data to be written * @param {IUploadOptions} [options={}] - Uploading options - * @returns {Promise} + * @returns {Promise} */ public static async bufferToUssFile(session: AbstractSession, ussname: string, - buffer: Buffer, - options: IUploadOptions = {}) { + fileBuffer: Buffer, + options: IUploadOptions = {}): Promise { ImperativeExpect.toNotBeEqual(options.record, true, ZosFilesMessages.unsupportedDataType.message); options.binary = options.binary ? options.binary : false; ImperativeExpect.toNotBeNullOrUndefined(ussname, ZosFilesMessages.missingUSSFileName.message); ussname = ZosFilesUtils.sanitizeUssPathForRestCall(ussname); - const parameters: string = ZosFilesConstants.RES_USS_FILES + "/" + ussname; - const headers: IHeaderContent[] = this.generateHeadersBasedOnOptions(options, "buffer"); + + const endpoint = ZosFilesConstants.RESOURCE + ZosFilesConstants.RES_USS_FILES + "/" + ussname; + const reqHeaders: IHeaderContent[] = this.generateHeadersBasedOnOptions(options, "buffer"); if (!options.binary) { - buffer = ZosFilesUtils.normalizeNewline(buffer); + fileBuffer = ZosFilesUtils.normalizeNewline(fileBuffer); + } + + // Options to use the buffer to write a file + const requestOptions: IOptionsFullResponse = { + resource: endpoint, + reqHeaders, + writeData: fileBuffer + }; + + // If requestor needs etag, add header + get "response" back + if (options.returnEtag) { + requestOptions.dataToReturn = [CLIENT_PROPERTY.response]; + } + const uploadRequest: IRestClientResponse = await ZosmfRestClient.putExpectFullResponse(session, requestOptions); + + // By default, apiResponse is empty when uploading + const apiResponse: any = {}; + + // Return Etag in apiResponse, if requested + if (options.returnEtag) { + apiResponse.etag = uploadRequest.response.headers.etag; } - return ZosmfRestClient.putExpectString(session, ZosFilesConstants.RESOURCE + parameters, headers, buffer); + return { + success: true, + commandResponse: ZosFilesMessages.dataSetUploadedSuccessfully.message, + apiResponse + }; } /** diff --git a/packages/zosfiles/src/methods/utilities/Utilities.ts b/packages/zosfiles/src/methods/utilities/Utilities.ts index e80c41de96..6ea34fd8f8 100644 --- a/packages/zosfiles/src/methods/utilities/Utilities.ts +++ b/packages/zosfiles/src/methods/utilities/Utilities.ts @@ -11,11 +11,11 @@ import { IOptions } from "../../doc/IOptions"; import { IZosFilesResponse } from "../../doc/IZosFilesResponse"; -import { AbstractSession, ImperativeExpect, Headers } from "@zowe/imperative"; +import { AbstractSession, ImperativeExpect, Headers, IHeaderContent } from "@zowe/imperative"; import { Tag } from "./doc/Tag"; import { ZosFilesMessages } from "../../constants/ZosFiles.messages"; import { ZosFilesConstants } from "../../constants/ZosFiles.constants"; -import { ZosmfRestClient, IHeaderContent, ZosmfHeaders } from "@zowe/core-for-zowe-sdk"; +import { ZosmfRestClient, ZosmfHeaders } from "@zowe/core-for-zowe-sdk"; import * as path from "path"; import { ZosFilesUtils } from "../../utils/ZosFilesUtils"; @@ -109,8 +109,8 @@ export class Utilities { if (Object.prototype.hasOwnProperty.call(jsonObj, "stdout")) { const stdout = jsonObj.stdout[0]; // Tests if binary tag set - return (stdout.indexOf("b ") > -1) || - (stdout.indexOf("UTF-") > -1) || (stdout.indexOf("ISO8859-") > -1) || (stdout.indexOf("IBM-850") > -1); + return stdout.indexOf("b ") > -1 || + stdout.indexOf("UTF-") > -1 || stdout.indexOf("ISO8859-") > -1 || stdout.indexOf("IBM-850") > -1; } return false; } diff --git a/packages/zosfiles/src/utils/ZosFilesAttributes.ts b/packages/zosfiles/src/utils/ZosFilesAttributes.ts index 79b8f9c954..f5b6cf3468 100644 --- a/packages/zosfiles/src/utils/ZosFilesAttributes.ts +++ b/packages/zosfiles/src/utils/ZosFilesAttributes.ts @@ -10,7 +10,7 @@ */ import * as fs from "fs"; -import * as minimatch from "minimatch"; +import { minimatch } from "minimatch"; import { ImperativeError, Logger, TextUtils } from "@zowe/imperative"; import { ZosFilesMessages } from "../constants/ZosFiles.messages"; import * as pathUtils from "path"; diff --git a/packages/zosfiles/src/utils/ZosFilesUtils.ts b/packages/zosfiles/src/utils/ZosFilesUtils.ts index 9397084aba..ab2a7c7e55 100644 --- a/packages/zosfiles/src/utils/ZosFilesUtils.ts +++ b/packages/zosfiles/src/utils/ZosFilesUtils.ts @@ -46,9 +46,9 @@ export class ZosFilesUtils { * @param {string} dataSet - data set to break up into folders */ public static getDirsFromDataSet(dataSet: string) { - let localDirectory = dataSet.replace(new RegExp(`\\${this.DSN_SEP}`, "g"), IO.FILE_DELIM).toLowerCase(); + let localDirectory = dataSet.replace(new RegExp(`\\${this.DSN_SEP}`, "g"), path.posix.sep).toLowerCase(); if (localDirectory.indexOf("(") >= 0 && localDirectory.indexOf(")") >= 0) { - localDirectory = localDirectory.replace(/\(/, IO.FILE_DELIM); + localDirectory = localDirectory.replace(/\(/, path.posix.sep); localDirectory = localDirectory.slice(0, -1); } return localDirectory; diff --git a/packages/zosfiles/typedoc.json b/packages/zosfiles/typedoc.json index 2b97359f2c..b15f87adc5 100644 --- a/packages/zosfiles/typedoc.json +++ b/packages/zosfiles/typedoc.json @@ -1,5 +1,6 @@ { "out": "./docs/typedoc/", - "exclude": "**/__tests__/**", + "exclude": ["**/__tests__/**"], + "entryPoints": ["src/index.ts"], "cleanOutputDir": true } \ No newline at end of file diff --git a/packages/zosjobs/CHANGELOG.md b/packages/zosjobs/CHANGELOG.md index 18cb80b765..5aa67fefef 100644 --- a/packages/zosjobs/CHANGELOG.md +++ b/packages/zosjobs/CHANGELOG.md @@ -2,6 +2,39 @@ All notable changes to the Zowe z/OS jobs SDK package will be documented in this file. +## Recent Changes + +- Update: Final prerelease + +## `8.0.0-next.202406111728` + +- BugFix: Fixed error in `DownloadJobs.downloadSpoolContentCommon` method when encoding parameter is not specified. [#2173](https://github.com/zowe/zowe-cli/pull/2173) + +## `8.0.0-next.202403131702` + +- BugFix: Removing stack trace for zosjobs errors. Added constant to JobsMessages.ts for error handling. [#2078](https://github.com/zowe/zowe-cli/pull/2078) + +## `8.0.0-next.202403041352` + +- BugFix: Updated engine to Node 18.12.0. [#2074](https://github.com/zowe/zowe-cli/pull/2074) + +## `8.0.0-next.202402261705` + +- BugFix: Updated dependencies for technical currency. [#2061](https://github.com/zowe/zowe-cli/pull/2061) +- BugFix: Updated engine to Node 16.7.0. [#2061](https://github.com/zowe/zowe-cli/pull/2061) + +## `8.0.0-next.202402211923` + +- Enhancement: New `SeachJob.searchJobs` class and method, which can be used to search spool files for a specified string or regular expression. + +## `8.0.0-next.202402021649` + +- LTS Breaking: Removed `getSpoolDownloadFile` use `getSpoolDownloadFilePath` instead + +## `8.0.0-next.202311132045` + +- Major: First major version bump for V3 + ## `7.26.1` - BugFix: Fixed error in `DownloadJobs.downloadSpoolContentCommon` method when encoding parameter is not specified. [#2173](https://github.com/zowe/zowe-cli/pull/2173) diff --git a/packages/zosjobs/__tests__/__resources__/api/GetJobsData.ts b/packages/zosjobs/__tests__/__resources__/api/GetJobsData.ts index b5a83c53f5..645c347331 100644 --- a/packages/zosjobs/__tests__/__resources__/api/GetJobsData.ts +++ b/packages/zosjobs/__tests__/__resources__/api/GetJobsData.ts @@ -80,7 +80,7 @@ export class GetJobsData { */ public static readonly SAMPLE_ACTIVE_JOB: IJob = { "retcode": null, - "jobname": "KELDA16$", + "jobname": "IBMUSER$", "status": "INPUT", "job-correlator": "J0003781USILDAMDD3CE8146.......:", "class": "A", @@ -88,7 +88,7 @@ export class GetJobsData { "jobid": "JOB03781", "url": "https://tso1:443/zosmf/restjobs/jobs/J0003781USILDAMDD3CE8146.......%3A", "phase-name": "Job is actively converting", - "owner": "KELDA16", + "owner": "IBMUSER", "subsystem": "JES2", "files-url": "https://tso1:443/zosmf/restjobs/jobs/J0003781USILDAMDD3CE8146.......%3A/files", "phase": 130 @@ -175,7 +175,7 @@ export class GetJobsData { */ public static readonly SAMPLE_IEFBR14_JCL: string = "//RUNMAIN JOB 105300000, JOB07172" + - "// USER=KELDA16" + + "// USER=IBMUSER" + "//* test" + "//EXEC EXEC PGM=IEFBR14,REGION=200M,MEMLIMIT=3G"; @@ -270,7 +270,7 @@ export class GetJobsData { " 0" + " 08.26.22 JOB01544 ---- MONDAY, 02 APR 2018 ----" + " 08.26.22 JOB01544 TSS7000I IBMUSER Last-Used 02 Apr 18 08:25 System=TEST Facility=TSO" + - " 08.26.22 JOB01544 TSS7001I Count=00411 Mode=Fail Locktime=None Name=ZOWE CLI TEST" + + " 08.26.22 JOB01544 TSS7001I Count=00411 Mode=Fail Locktime=None Name=USER, IBM" + " 08.26.22 JOB01544 $HASP373 RUNMAIN STARTED - WLM INIT - SRVCLASS BATSTWLM - SYS TEST" + " 08.26.22 JOB01544 IEF403I RUNMAIN - STARTED - TIME=08.26.22" + " 08.26.22 JOB01544 CAJR250I STEPNAME STEP PGM= CCODE EST-COST EXCPS ELAPSED TOT-CPU PAGE-IN PAGE-OT SWAP-IN SWAP-OT" + diff --git a/packages/zosjobs/__tests__/__system__/DownloadJobs.system.test.ts b/packages/zosjobs/__tests__/__system__/DownloadJobs.system.test.ts index dbe67218e6..ce1e1bedaa 100644 --- a/packages/zosjobs/__tests__/__system__/DownloadJobs.system.test.ts +++ b/packages/zosjobs/__tests__/__system__/DownloadJobs.system.test.ts @@ -73,10 +73,8 @@ describe("Download Jobs - System tests", () => { SYSAFF = testEnvironment.systemTestProperties.zosjobs.sysaff; }); - afterEach((done: any) => { // eslint-disable-line jest/no-done-callback - require("rimraf")(outputDirectory, {maxBusyTries: 10}, (err?: Error) => { - done(err); - }); + afterEach(() => { + require("rimraf").sync(outputDirectory, {maxBusyRetries: 10}); }); afterAll(async () => { @@ -118,8 +116,11 @@ describe("Download Jobs - System tests", () => { encoding: "IBM-037" }); - // eslint-disable-next-line deprecation/deprecation - const expectedFile = DownloadJobs.getSpoolDownloadFile(alteredjesJCLJobFile, false, downloadDir); + const expectedFile = DownloadJobs.getSpoolDownloadFilePath({ + jobFile: alteredjesJCLJobFile, + omitJobidDirectory: false, + outDir: downloadDir + }); expect(IO.existsSync(expectedFile)).toEqual(true); expect(IO.readFileSync(expectedFile).toString()).toContain("¬"); expect(IO.readFileSync(expectedFile).toString()).not.toContain("^"); @@ -135,8 +136,11 @@ describe("Download Jobs - System tests", () => { }); for (const file of alteredjobFiles) { - // eslint-disable-next-line deprecation/deprecation - const expectedFile = DownloadJobs.getSpoolDownloadFile(file, false, downloadDir); + const expectedFile = DownloadJobs.getSpoolDownloadFilePath({ + jobFile: file, + omitJobidDirectory: false, + outDir: downloadDir + }); expect(IO.existsSync(expectedFile)).toEqual(true); if (file.ddname === "JESJCL") { expect(IO.readFileSync(expectedFile).toString()).toContain("¬"); @@ -149,14 +153,17 @@ describe("Download Jobs - System tests", () => { describe("Positive tests", () => { it("should be able to download a single DD from job output to specified directory", async () => { - const downloadDir = outputDirectory + "/downloadsingle/"; await DownloadJobs.downloadSpoolContentCommon(REAL_SESSION, { - outDir: downloadDir, + outDir: outputDirectory, jobFile: jesJCLJobFile }); - expect(IO.existsSync(downloadDir)).toEqual(true); - // eslint-disable-next-line deprecation/deprecation - const expectedFile = DownloadJobs.getSpoolDownloadFile(jesJCLJobFile, false, downloadDir); + const expectedFile = DownloadJobs.getSpoolDownloadFilePath( + { + jobFile: jesJCLJobFile, + omitJobidDirectory: false, + outDir: outputDirectory + } + ); expect(IO.existsSync(expectedFile)).toEqual(true); expect(IO.readFileSync(expectedFile).toString()).toContain("EXEC PGM=IEFBR14"); }); @@ -165,39 +172,49 @@ describe("Download Jobs - System tests", () => { await DownloadJobs.downloadSpoolContent(REAL_SESSION, jesJCLJobFile ); - // eslint-disable-next-line deprecation/deprecation - const expectedFile = DownloadJobs.getSpoolDownloadFile(jesJCLJobFile, false); + const expectedFile = DownloadJobs.getSpoolDownloadFilePath( + { + jobFile: jesJCLJobFile, + omitJobidDirectory: false + } + ); expect(IO.existsSync(expectedFile)).toEqual(true); expect(IO.readFileSync(expectedFile).toString()).toContain("EXEC PGM=IEFBR14"); }); it("should be able to download all DDs from job output", async () => { - const downloadDir = outputDirectory + "/downloadall/"; await DownloadJobs.downloadAllSpoolContentCommon(REAL_SESSION, { - outDir: downloadDir, + outDir: outputDirectory, jobid, jobname }); - - for (const file of jobFiles) { - // eslint-disable-next-line deprecation/deprecation - const expectedFile = DownloadJobs.getSpoolDownloadFile(file, false, downloadDir); - expect(IO.existsSync(expectedFile)).toEqual(true); - } + const expectedFile = DownloadJobs.getSpoolDownloadFilePath( + { + jobFile: jesJCLJobFile, + omitJobidDirectory: false, + outDir: outputDirectory + } + ); + expect(IO.existsSync(expectedFile)).toEqual(true); + expect(IO.readFileSync(expectedFile).toString()).toContain("EXEC PGM=IEFBR14"); }); it("should be able to download all DDs from job output in binary mode", async () => { - const downloadDir = outputDirectory + "/downloadall/"; await DownloadJobs.downloadAllSpoolContentCommon(REAL_SESSION, { - outDir: downloadDir, + outDir: outputDirectory, + binary: true, jobid, - jobname, - binary: true + jobname }); for (const file of jobFiles) { - // eslint-disable-next-line deprecation/deprecation - const expectedFile = DownloadJobs.getSpoolDownloadFile(file, false, downloadDir); + const expectedFile = DownloadJobs.getSpoolDownloadFilePath( + { + jobFile: file, + omitJobidDirectory: false, + outDir: outputDirectory + } + ); expect(IO.existsSync(expectedFile)).toEqual(true); if (file.ddname === "JESJCL") { // Record is 90 characters long, starts with 8 spaces @@ -209,17 +226,21 @@ describe("Download Jobs - System tests", () => { }); it("should be able to download all DDs from job output in record mode", async () => { - const downloadDir = outputDirectory + "/downloadall/"; await DownloadJobs.downloadAllSpoolContentCommon(REAL_SESSION, { - outDir: downloadDir, + outDir: outputDirectory, jobid, jobname, record: true }); for (const file of jobFiles) { - // eslint-disable-next-line deprecation/deprecation - const expectedFile = DownloadJobs.getSpoolDownloadFile(file, false, downloadDir); + const expectedFile = DownloadJobs.getSpoolDownloadFilePath( + { + jobFile: file, + omitJobidDirectory: false, + outDir: outputDirectory + } + ); expect(IO.existsSync(expectedFile)).toEqual(true); if (file.ddname === "JESJCL") { // Record is 90 characters long, starts with 8 spaces @@ -240,17 +261,21 @@ describe("Download Jobs - System tests", () => { await MonitorJobs.waitForJobOutputStatus(REAL_SESSION, job); - const downloadDir = outputDirectory + "/downloadsteps/"; await DownloadJobs.downloadAllSpoolContentCommon(REAL_SESSION, { - outDir: downloadDir, + outDir: outputDirectory, jobid: job.jobid, jobname: job.jobname }); const expectedExt = DownloadJobs.DEFAULT_JOBS_OUTPUT_FILE_EXT; for (const file of await GetJobs.getSpoolFilesForJob(REAL_SESSION, job)) { - // eslint-disable-next-line deprecation/deprecation - const expectedFile = DownloadJobs.getSpoolDownloadFile(file, false, downloadDir); + const expectedFile = DownloadJobs.getSpoolDownloadFilePath( + { + jobFile: file, + omitJobidDirectory: false, + outDir: outputDirectory + } + ); expect(IO.existsSync(expectedFile)).toEqual(true); if (file.stepname !== "JES2") { @@ -264,6 +289,7 @@ describe("Download Jobs - System tests", () => { describe("Negative tests", () => { let badJobFile: IJobFile; + let err: Error | ImperativeError |any; const badID = 9999; beforeAll(() => { @@ -274,25 +300,22 @@ describe("Download Jobs - System tests", () => { it("should encounter an error if a non existent spool file is passed to downloadSpoolContentCommon", async () => { - let err: Error | ImperativeError; try { await DownloadJobs.downloadSpoolContentCommon(REAL_SESSION, { jobFile: badJobFile, + jobname: "FAKEJOB", + jobid: "FAKEJOBID", outDir: outputDirectory }); } catch (e) { err = e; } expect(err).toBeDefined(); - expect(err instanceof ImperativeError).toEqual(true); - expect(err.message).toContain(jobname); - expect(err.message).toContain(jobid); - expect(err.message).toContain("does not contain"); + expect(JSON.parse(err.causeErrors).message).toContain("does not contain spool file"); }); it("should encounter an error if a non existent jobname/jobid is passed to downloadAllSpoolContentCommon", async () => { - let err: Error | ImperativeError; try { await DownloadJobs.downloadAllSpoolContentCommon(REAL_SESSION, { jobname: "FAKEJOB", @@ -303,25 +326,18 @@ describe("Download Jobs - System tests", () => { err = e; } expect(err).toBeDefined(); - expect(err instanceof ImperativeError).toEqual(true); - expect(err.message).toContain("FAKEJOB"); - expect(err.message).toContain("JOBABCD"); - expect(err.message).toContain("Failed to lookup"); + expect(err.message).toContain("queryJobs failed"); }); it("should encounter an error if a non existent spool file is passed to downloadSpoolContent", async () => { - let err: Error | ImperativeError; try { await DownloadJobs.downloadSpoolContent(REAL_SESSION, badJobFile); } catch (e) { err = e; } expect(err).toBeDefined(); - expect(err instanceof ImperativeError).toEqual(true); - expect(err.message).toContain(jobname); - expect(err.message).toContain(jobid); - expect(err.message).toContain("does not contain"); + expect(JSON.parse(err.causeErrors).message).toContain("does not contain spool file"); }); }); @@ -332,6 +348,7 @@ describe("Download Jobs - System tests - Encoded", () => { let jobname: string; let jobFiles: IJobFile[]; let jesJCLJobFile: IJobFile; + beforeAll(async () => { testEnvironment = await TestEnvironment.setUp({ testName: "zos_download_jobs_encoded" @@ -363,10 +380,8 @@ describe("Download Jobs - System tests - Encoded", () => { SYSAFF = testEnvironment.systemTestProperties.zosjobs.sysaff; }); - afterEach((done: any) => { // eslint-disable-line jest/no-done-callback - require("rimraf")(outputDirectory, {maxBusyTries: 10}, (err?: Error) => { - done(err); - }); + afterEach(() => { + require("rimraf").sync(outputDirectory, {maxBusyTries: 10}); }); afterAll(async () => { @@ -374,16 +389,19 @@ describe("Download Jobs - System tests - Encoded", () => { }); describe("Positive tests", () => { - it("should be able to download a single DD from job output to specified directory", async () => { - const downloadDir = outputDirectory + "/downloadsingle/"; await DownloadJobs.downloadSpoolContentCommon(REAL_SESSION, { - outDir: downloadDir, + outDir: outputDirectory, jobFile: jesJCLJobFile }); - expect(IO.existsSync(downloadDir)).toEqual(true); - // eslint-disable-next-line deprecation/deprecation - const expectedFile = DownloadJobs.getSpoolDownloadFile(jesJCLJobFile, false, downloadDir); + expect(IO.existsSync(outputDirectory)).toEqual(true); + const expectedFile = DownloadJobs.getSpoolDownloadFilePath( + { + jobFile: jesJCLJobFile, + omitJobidDirectory: false, + outDir: outputDirectory + } + ); expect(IO.existsSync(expectedFile)).toEqual(true); expect(IO.readFileSync(expectedFile).toString()).toContain("EXEC PGM=IEFBR14"); }); @@ -392,39 +410,51 @@ describe("Download Jobs - System tests - Encoded", () => { await DownloadJobs.downloadSpoolContent(REAL_SESSION, jesJCLJobFile ); - // eslint-disable-next-line deprecation/deprecation - const expectedFile = DownloadJobs.getSpoolDownloadFile(jesJCLJobFile, false); + const expectedFile = DownloadJobs.getSpoolDownloadFilePath( + { + jobFile: jesJCLJobFile, + omitJobidDirectory: false + } + ); expect(IO.existsSync(expectedFile)).toEqual(true); expect(IO.readFileSync(expectedFile).toString()).toContain("EXEC PGM=IEFBR14"); }); it("should be able to download all DDs from job output", async () => { - const downloadDir = outputDirectory + "/downloadall/"; await DownloadJobs.downloadAllSpoolContentCommon(REAL_SESSION, { - outDir: downloadDir, + outDir: outputDirectory, jobid, jobname }); for (const file of jobFiles) { - // eslint-disable-next-line deprecation/deprecation - const expectedFile = DownloadJobs.getSpoolDownloadFile(file, false, downloadDir); + const expectedFile = DownloadJobs.getSpoolDownloadFilePath( + { + jobFile: file, + omitJobidDirectory: false, + outDir: outputDirectory + } + ); expect(IO.existsSync(expectedFile)).toEqual(true); } }); it("should be able to download all DDs from job output in binary mode", async () => { - const downloadDir = outputDirectory + "/downloadall/"; await DownloadJobs.downloadAllSpoolContentCommon(REAL_SESSION, { - outDir: downloadDir, + outDir: outputDirectory, jobid, jobname, binary: true }); for (const file of jobFiles) { - // eslint-disable-next-line deprecation/deprecation - const expectedFile = DownloadJobs.getSpoolDownloadFile(file, false, downloadDir); + const expectedFile = DownloadJobs.getSpoolDownloadFilePath( + { + jobFile: file, + omitJobidDirectory: false, + outDir: outputDirectory + } + ); expect(IO.existsSync(expectedFile)).toEqual(true); if (file.ddname === "JESJCL") { // Record is 90 characters long, starts with 8 spaces @@ -436,17 +466,21 @@ describe("Download Jobs - System tests - Encoded", () => { }); it("should be able to download all DDs from job output in record mode", async () => { - const downloadDir = outputDirectory + "/downloadall/"; await DownloadJobs.downloadAllSpoolContentCommon(REAL_SESSION, { - outDir: downloadDir, + outDir: outputDirectory, jobid, jobname, record: true }); for (const file of jobFiles) { - // eslint-disable-next-line deprecation/deprecation - const expectedFile = DownloadJobs.getSpoolDownloadFile(file, false, downloadDir); + const expectedFile = DownloadJobs.getSpoolDownloadFilePath( + { + jobFile: file, + omitJobidDirectory: false, + outDir: outputDirectory + } + ); expect(IO.existsSync(expectedFile)).toEqual(true); if (file.ddname === "JESJCL") { // Record is 90 characters long, starts with 8 spaces @@ -467,17 +501,21 @@ describe("Download Jobs - System tests - Encoded", () => { await MonitorJobs.waitForJobOutputStatus(REAL_SESSION, job); - const downloadDir = outputDirectory + "/downloadsteps/"; await DownloadJobs.downloadAllSpoolContentCommon(REAL_SESSION, { - outDir: downloadDir, + outDir: outputDirectory, jobid: job.jobid, jobname: job.jobname }); const expectedExt = DownloadJobs.DEFAULT_JOBS_OUTPUT_FILE_EXT; for (const file of await GetJobs.getSpoolFilesForJob(REAL_SESSION, job)) { - // eslint-disable-next-line deprecation/deprecation - const expectedFile = DownloadJobs.getSpoolDownloadFile(file, false, downloadDir); + const expectedFile = DownloadJobs.getSpoolDownloadFilePath( + { + jobFile: file, + omitJobidDirectory: false, + outDir: outputDirectory + } + ); expect(IO.existsSync(expectedFile)).toEqual(true); if (file.stepname !== "JES2") { @@ -487,4 +525,4 @@ describe("Download Jobs - System tests - Encoded", () => { } }, LONG_TIMEOUT); }); -}); \ No newline at end of file +}); diff --git a/packages/zosjobs/__tests__/__system__/GetJobs.system.test.ts b/packages/zosjobs/__tests__/__system__/GetJobs.system.test.ts index 94732d63da..5a65c75ec6 100644 --- a/packages/zosjobs/__tests__/__system__/GetJobs.system.test.ts +++ b/packages/zosjobs/__tests__/__system__/GetJobs.system.test.ts @@ -263,9 +263,10 @@ describe("Get Jobs - System Tests", () => { expect(err).toBeDefined(); expect(err instanceof ImperativeError).toBe(true); const trimmedErrorMessage = trimMessage(err.message); - expect(trimmedErrorMessage).toContain("category: 6"); - expect(trimmedErrorMessage).toContain("reason: 4"); - expect(trimmedErrorMessage).toContain("rc: 4"); + const jsonCauseErrors = JSON.parse(err.causeErrors); + expect(jsonCauseErrors.category).toEqual(6); + expect(jsonCauseErrors.reason).toEqual(4); + expect(jsonCauseErrors.rc).toEqual(4); expect(trimmedErrorMessage).toContain("status 400"); expect(trimmedErrorMessage).toContain("prefix query parameter"); }); @@ -315,14 +316,14 @@ describe("Get Jobs - System Tests", () => { }, LONG_TIMEOUT); it("should throw an error if we specify a job ID that doesn't exist", async () => { - let err: Error | ImperativeError; + let err: ImperativeError; try { await GetJobs.getJob(REAL_SESSION, "J999999"); } catch (e) { err = e; } expect(err).toBeDefined(); - expect(err.message).toContain("not found"); + expect(err.causeErrors).toContain("Zero jobs"); }); it("should return no jobs for a prefix that doesn't match anything", async () => { @@ -400,9 +401,10 @@ describe("Get Jobs - System Tests", () => { expect(err).toBeDefined(); expect(err instanceof ImperativeError).toBe(true); const trimmedErrorMessage = trimMessage(err.message); - expect(trimmedErrorMessage).toContain("category: 6"); - expect(trimmedErrorMessage).toContain("reason: 4"); - expect(trimmedErrorMessage).toContain("rc: 4"); + const jsonCauseErrors = JSON.parse(err.causeErrors); + expect(jsonCauseErrors.category).toEqual(6); + expect(jsonCauseErrors.reason).toEqual(4); + expect(jsonCauseErrors.rc).toEqual(4); expect(trimmedErrorMessage).toContain("status 400"); expect(trimmedErrorMessage).toContain("owner query parameter"); }); @@ -491,9 +493,10 @@ describe("Get Status APIs", () => { expect(err).toBeDefined(); expect(err instanceof ImperativeError).toBe(true); const trimmedErrorMessage = trimMessage(err.message); - expect(trimmedErrorMessage).toContain("category: 6"); - expect(trimmedErrorMessage).toContain("reason: 7"); - expect(trimmedErrorMessage).toContain("rc: 4"); + const jsonCauseErrors = JSON.parse(err.causeErrors); + expect(jsonCauseErrors.category).toEqual(6); + expect(jsonCauseErrors.reason).toEqual(7); + expect(jsonCauseErrors.rc).toEqual(4); expect(trimmedErrorMessage).toContain("status 400"); }); @@ -507,9 +510,10 @@ describe("Get Status APIs", () => { expect(err).toBeDefined(); expect(err instanceof ImperativeError).toBe(true); const trimmedErrorMessage = trimMessage(err.message); - expect(trimmedErrorMessage).toContain("category: 6"); - expect(trimmedErrorMessage).toContain("reason: 7"); - expect(trimmedErrorMessage).toContain("rc: 4"); + const jsonCauseErrors = JSON.parse(err.causeErrors); + expect(jsonCauseErrors.category).toEqual(6); + expect(jsonCauseErrors.reason).toEqual(7); + expect(jsonCauseErrors.rc).toEqual(4); expect(trimmedErrorMessage).toContain("status 400"); }); }); @@ -609,9 +613,10 @@ describe("Get Status APIs", () => { expect(err).toBeDefined(); expect(err instanceof ImperativeError).toBe(true); const trimmedErrorMessage = trimMessage(err.message); - expect(trimmedErrorMessage).toContain("rc: 4"); - expect(trimmedErrorMessage).toContain("category: 6"); - expect(trimmedErrorMessage).toContain("reason: 7"); + const jsonCauseErrors = JSON.parse(err.causeErrors); + expect(jsonCauseErrors.category).toEqual(6); + expect(jsonCauseErrors.reason).toEqual(7); + expect(jsonCauseErrors.rc).toEqual(4); expect(trimmedErrorMessage).toContain("status 400"); expect(trimmedErrorMessage).toContain("JOB123"); }); @@ -626,9 +631,10 @@ describe("Get Status APIs", () => { expect(err).toBeDefined(); expect(err instanceof ImperativeError).toBe(true); const trimmedErrorMessage = trimMessage(err.message); - expect(trimmedErrorMessage).toContain("category: 6"); - expect(trimmedErrorMessage).toContain("reason: 7"); - expect(trimmedErrorMessage).toContain("rc: 4"); + const jsonCauseErrors = JSON.parse(err.causeErrors); + expect(jsonCauseErrors.category).toEqual(6); + expect(jsonCauseErrors.reason).toEqual(7); + expect(jsonCauseErrors.rc).toEqual(4); expect(trimmedErrorMessage).toContain("status 400"); }); }); @@ -748,9 +754,10 @@ describe("Get Status APIs", () => { expect(err).toBeDefined(); expect(err instanceof ImperativeError).toBe(true); const trimmedErrorMessage = trimMessage(err.message); - expect(trimmedErrorMessage).toContain("category: 6"); - expect(trimmedErrorMessage).toContain("reason: 7"); - expect(trimmedErrorMessage).toContain("rc: 4"); + const jsonCauseErrors = JSON.parse(err.causeErrors); + expect(jsonCauseErrors.category).toEqual(6); + expect(jsonCauseErrors.reason).toEqual(7); + expect(jsonCauseErrors.rc).toEqual(4); expect(trimmedErrorMessage).toContain("status 400"); }); @@ -764,9 +771,10 @@ describe("Get Status APIs", () => { expect(err).toBeDefined(); expect(err instanceof ImperativeError).toBe(true); const trimmedErrorMessage = trimMessage(err.message); - expect(trimmedErrorMessage).toContain("category: 6"); - expect(trimmedErrorMessage).toContain("reason: 7"); - expect(trimmedErrorMessage).toContain("rc: 4"); + const jsonCauseErrors = JSON.parse(err.causeErrors); + expect(jsonCauseErrors.category).toEqual(6); + expect(jsonCauseErrors.reason).toEqual(7); + expect(jsonCauseErrors.rc).toEqual(4); expect(trimmedErrorMessage).toContain("status 400"); }); }); @@ -861,9 +869,10 @@ describe("Get spool APIs", () => { expect(JSON.parse(error.causeErrors).reason).toMatchSnapshot(); expect(JSON.parse(error.causeErrors).category).toMatchSnapshot(); const trimmedErrorMessage = trimMessage(error.message); - expect(trimmedErrorMessage).toContain("category: 6"); - expect(trimmedErrorMessage).toContain("reason: 10"); - expect(trimmedErrorMessage).toContain("rc: 4"); + const jsonCauseErrors = JSON.parse(error.causeErrors); + expect(jsonCauseErrors.category).toEqual(6); + expect(jsonCauseErrors.reason).toEqual(10); + expect(jsonCauseErrors.rc).toEqual(4); expect(trimmedErrorMessage).toContain("status 400"); }, LONG_TIMEOUT); }); @@ -1203,14 +1212,14 @@ describe("Get Jobs - System Tests - Encoded", () => { }, LONG_TIMEOUT); it("should throw an error if we specify a job ID that doesn't exist", async () => { - let err: Error | ImperativeError; + let err: ImperativeError; try { await GetJobs.getJob(REAL_SESSION, "J999999"); } catch (e) { err = e; } expect(err).toBeDefined(); - expect(err.message).toContain("not found"); + expect(err.causeErrors).toContain("Zero jobs"); }); it("should return no jobs for a prefix that doesn't match anything", async () => { diff --git a/packages/zosjobs/__tests__/__system__/MonitorJobs.system.test.ts b/packages/zosjobs/__tests__/__system__/MonitorJobs.system.test.ts index 55999d62fa..427fa943f4 100644 --- a/packages/zosjobs/__tests__/__system__/MonitorJobs.system.test.ts +++ b/packages/zosjobs/__tests__/__system__/MonitorJobs.system.test.ts @@ -113,10 +113,11 @@ describe("System Tests - Monitor Jobs", () => { // const regex: RegExp = new RegExp(fs.readFileSync(TEST_REGEX_DIR + "/not_found_job.regex").toString(), "g"); // expect(regex.test(error.message)).toBe(true); const trimmedErrorMessage = trimMessage(error.message); + const jsonCauseErrors = JSON.parse(error.causeErrors); expect(trimmedErrorMessage).toContain("Error obtaining status for jobname \"JOB1\" jobid \"JOB123\""); - expect(trimmedErrorMessage).toContain("category: 6"); - expect(trimmedErrorMessage).toContain("reason: 10"); - expect(trimmedErrorMessage).toContain("rc: 4"); + expect(jsonCauseErrors.category).toEqual(6); + expect(jsonCauseErrors.reason).toEqual(10); + expect(jsonCauseErrors.rc).toEqual(4); expect(trimmedErrorMessage).toContain("status 400"); expect(trimmedErrorMessage).toContain("No job found for reference"); }); @@ -197,10 +198,11 @@ describe("System Tests - Monitor Jobs", () => { // const regex: RegExp = new RegExp(fs.readFileSync(TEST_REGEX_DIR + "/not_found_job.regex").toString(), "g"); // expect(regex.test(error.message)).toBe(true); const trimmedErrorMessage = trimMessage(error.message); + const jsonCauseErrors = JSON.parse(error.causeErrors); expect(trimmedErrorMessage).toContain("Error obtaining status for jobname \"JOB1\" jobid \"JOB123\""); - expect(trimmedErrorMessage).toContain("category: 6"); - expect(trimmedErrorMessage).toContain("reason: 10"); - expect(trimmedErrorMessage).toContain("rc: 4"); + expect(jsonCauseErrors.category).toEqual(6); + expect(jsonCauseErrors.reason).toEqual(10); + expect(jsonCauseErrors.rc).toEqual(4); expect(trimmedErrorMessage).toContain("status 400"); expect(trimmedErrorMessage).toContain("No job found for reference"); }); @@ -280,10 +282,11 @@ describe("System Tests - Monitor Jobs", () => { // const regex: RegExp = new RegExp(fs.readFileSync(TEST_REGEX_DIR + "/invalid_jobname.regex").toString(), "g"); // expect(regex.test(error.message)).toBe(true); const trimmedErrorMessage = trimMessage(error.message); + const jsonCauseErrors = JSON.parse(error.causeErrors); expect(trimmedErrorMessage).toContain("Error obtaining status for jobname \"(((((\" jobid \"JOB123\""); - expect(trimmedErrorMessage).toContain("category: 6"); - expect(trimmedErrorMessage).toContain("reason: 7"); - expect(trimmedErrorMessage).toContain("rc: 4"); + expect(jsonCauseErrors.category).toEqual(6); + expect(jsonCauseErrors.reason).toEqual(7); + expect(jsonCauseErrors.rc).toEqual(4); expect(trimmedErrorMessage).toContain("status 400"); expect(trimmedErrorMessage).toContain("No match for method GET and pathInfo"); }); @@ -300,10 +303,11 @@ describe("System Tests - Monitor Jobs", () => { // const regex: RegExp = new RegExp(fs.readFileSync(TEST_REGEX_DIR + "/invalid_jobid.regex").toString(), "g"); // expect(regex.test(error.message)).toBe(true); const trimmedErrorMessage = trimMessage(error.message); + const jsonCauseErrors = JSON.parse(error.causeErrors); expect(trimmedErrorMessage).toContain("Error obtaining status for jobname \"JOB1\" jobid \"(\""); - expect(trimmedErrorMessage).toContain("category: 6"); - expect(trimmedErrorMessage).toContain("reason: 7"); - expect(trimmedErrorMessage).toContain("rc: 4"); + expect(jsonCauseErrors.category).toEqual(6); + expect(jsonCauseErrors.reason).toEqual(7); + expect(jsonCauseErrors.rc).toEqual(4); expect(trimmedErrorMessage).toContain("status 400"); expect(trimmedErrorMessage).toContain("No match for method GET and pathInfo"); }); @@ -320,10 +324,11 @@ describe("System Tests - Monitor Jobs", () => { // const regex: RegExp = new RegExp(fs.readFileSync(TEST_REGEX_DIR + "/not_found_job.regex").toString(), "g"); // expect(regex.test(error.message)).toBe(true); const trimmedErrorMessage = trimMessage(error.message); + const jsonCauseErrors = JSON.parse(error.causeErrors); expect(trimmedErrorMessage).toContain("Error obtaining status for jobname \"JOB1\" jobid \"JOB123\""); - expect(trimmedErrorMessage).toContain("category: 6"); - expect(trimmedErrorMessage).toContain("reason: 10"); - expect(trimmedErrorMessage).toContain("rc: 4"); + expect(jsonCauseErrors.category).toEqual(6); + expect(jsonCauseErrors.reason).toEqual(10); + expect(jsonCauseErrors.rc).toEqual(4); expect(trimmedErrorMessage).toContain("status 400"); expect(trimmedErrorMessage).toContain("No job found for reference"); }); @@ -466,10 +471,11 @@ describe("System Tests - Monitor Jobs", () => { // const regex: RegExp = new RegExp(fs.readFileSync(TEST_REGEX_DIR + "/polling_job_deleted.regex").toString(), "g"); // expect(regex.test(error.message)).toBe(true); const trimmedErrorMessage = trimMessage(error.message); + const jsonCauseErrors = JSON.parse(error.causeErrors); expect(trimmedErrorMessage).toContain("Error obtaining status for jobname"); - expect(trimmedErrorMessage).toContain("category: 6"); - expect(trimmedErrorMessage).toContain("reason: 10"); - expect(trimmedErrorMessage).toContain("rc: 4"); + expect(jsonCauseErrors.category).toEqual(6); + expect(jsonCauseErrors.reason).toEqual(10); + expect(jsonCauseErrors.rc).toEqual(4); expect(trimmedErrorMessage).toContain("status 400"); expect(trimmedErrorMessage).toContain("No job found for reference"); if (!doneCalled) { @@ -962,10 +968,11 @@ describe("System Tests - Monitor Jobs - Encoded", () => { // const regex: RegExp = new RegExp(fs.readFileSync(TEST_REGEX_DIR + "/polling_job_deleted.regex").toString(), "g"); // expect(regex.test(error.message)).toBe(true); const trimmedErrorMessage = trimMessage(error.message); + const jsonCauseErrors = JSON.parse(error.causeErrors); expect(trimmedErrorMessage).toContain("Error obtaining status for jobname"); - expect(trimmedErrorMessage).toContain("category: 6"); - expect(trimmedErrorMessage).toContain("reason: 10"); - expect(trimmedErrorMessage).toContain("rc: 4"); + expect(jsonCauseErrors.category).toEqual(6); + expect(jsonCauseErrors.reason).toEqual(10); + expect(jsonCauseErrors.rc).toEqual(4); expect(trimmedErrorMessage).toContain("status 400"); expect(trimmedErrorMessage).toContain("No job found for reference"); if (!doneCalled) { diff --git a/packages/zosjobs/__tests__/__system__/SearchJobs.system.test.ts b/packages/zosjobs/__tests__/__system__/SearchJobs.system.test.ts new file mode 100644 index 0000000000..5d9c45e593 --- /dev/null +++ b/packages/zosjobs/__tests__/__system__/SearchJobs.system.test.ts @@ -0,0 +1,120 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ImperativeError, Session } from "@zowe/imperative"; +import { DeleteJobs, GetJobs, IJob, SearchJobs } from "../../src"; +import { ITestEnvironment } from "@zowe/cli-test-utils"; +import { TestEnvironment } from "../../../../__tests__/__src__/environment/TestEnvironment"; +import { ITestPropertiesSchema } from "../../../../__tests__/__src__/properties/ITestPropertiesSchema"; + +/**********************************************************************************/ +let ACCOUNT: string; + +// The job class for holding jobs on the input queue +let JOBCLASS: string; +let SYSAFF: string; + +// Session to use for the tests +let REAL_SESSION: Session; + +// Invalid credentials session +let INVALID_SESSION: Session; +// The job name - should be the same for cleanup, etc. +const SIX_CHARS = 6; +let MONITOR_JOB_NAME: string; +const TEST_JOB_NAME = "TSTMB"; +// Sample JCL - TODO replace by JCL resources +let JCL: string; + +let defaultSystem: ITestPropertiesSchema; +let testEnvironment: ITestEnvironment; + +// Utility function to cleanup +async function cleanTestJobs(prefix: string) { + // The tests may submit jobs - we will clean every job that may have been left by failures, etc. + const jobs: IJob[] = await GetJobs.getJobsCommon(REAL_SESSION, {owner: REAL_SESSION.ISession.user, prefix: prefix + "*"}); + if (jobs.length > 0) { + for (const job of jobs) { + try { + await DeleteJobs.deleteJob(REAL_SESSION, job.jobname, job.jobid); + } catch (e) { + // Don't worry about it + } + } + } +} + +describe("Search Jobs - System Tests", () => { + + beforeAll(async () => { + testEnvironment = await TestEnvironment.setUp({ + testName: "zos_search_jobs" + }); + defaultSystem = testEnvironment.systemTestProperties; + + REAL_SESSION = TestEnvironment.createZosmfSession(testEnvironment); + + INVALID_SESSION = new Session({ + user: "fakeuser", + password: "fake", + hostname: defaultSystem.zosmf.host, + port: defaultSystem.zosmf.port, + basePath: defaultSystem.zosmf.basePath, + type: "basic", + rejectUnauthorized: false + }); + + ACCOUNT = defaultSystem.tso.account; + MONITOR_JOB_NAME = REAL_SESSION.ISession.user?.toUpperCase().substring(0, SIX_CHARS) + "G"; + + JOBCLASS = testEnvironment.systemTestProperties.zosjobs.jobclass; + SYSAFF = testEnvironment.systemTestProperties.zosjobs.sysaff; + + // TODO: What string goes in the removed section? + JCL = + "//" + MONITOR_JOB_NAME + " JOB '" + ACCOUNT + "',CLASS=" + JOBCLASS + "\n" + + "//IEFBR14 EXEC PGM=IEFBR14"; // GetJobs + }); + + // Cleanup before & after each test - this will ensure that hopefully no jobs are left outstanding (or are currently + // outstanding) when the tests run + beforeEach(async () => { + await cleanTestJobs(MONITOR_JOB_NAME); + await cleanTestJobs(TEST_JOB_NAME); + }); + afterEach(async () => { + await cleanTestJobs(MONITOR_JOB_NAME); + await cleanTestJobs(TEST_JOB_NAME); + }); + + /**********************************************/ + // API methods "SearchJobs..." system tests + describe("Search Jobs APIs", () => { + + /**********************************************/ + // API methods "Searchobs" system tests + describe("search jobs API", () => { + describe("invalid request error handling", () => { + it("should detect and surface an error for an invalid user", async () => { + let err; + try { + await SearchJobs.searchJobs(INVALID_SESSION,{jobName: "IBMUSER"}); + } catch (e) { + err = e; + } + expect(err).toBeDefined(); + expect(err instanceof ImperativeError).toBe(true); + expect(err.message).toContain("status 401"); // unauthorized - bad credentials + }); + }); + }); + }); +}); \ No newline at end of file diff --git a/packages/zosjobs/__tests__/__system__/SubmitJobs.system.test.ts b/packages/zosjobs/__tests__/__system__/SubmitJobs.system.test.ts index 985a0e48ae..a97bfd2b68 100644 --- a/packages/zosjobs/__tests__/__system__/SubmitJobs.system.test.ts +++ b/packages/zosjobs/__tests__/__system__/SubmitJobs.system.test.ts @@ -56,7 +56,7 @@ describe("Submit Jobs - System Tests", () => { jobUSSFile = testEnvironment.systemTestProperties.zosjobs.iefbr14USSFile; const maxJobNamePrefixLength = 5; iefbr14JCL = "//" + systemProps.zosmf.user.toUpperCase().substring(0, maxJobNamePrefixLength) + "J JOB " + account + - ",'Brightside Test',MSGLEVEL=(1,1),MSGCLASS=4,CLASS=C\n" + + ",'Zowe Test',MSGLEVEL=(1,1),MSGCLASS=4,CLASS=C\n" + "//EXEC PGM=IEFBR14"; }); diff --git a/packages/zosjobs/__tests__/__unit__/GetJobs.unit.test.ts b/packages/zosjobs/__tests__/__unit__/GetJobs.unit.test.ts index 9e82458ff8..f8a0e3138d 100644 --- a/packages/zosjobs/__tests__/__unit__/GetJobs.unit.test.ts +++ b/packages/zosjobs/__tests__/__unit__/GetJobs.unit.test.ts @@ -10,7 +10,7 @@ */ import { ZosmfRestClient } from "@zowe/core-for-zowe-sdk"; -import { AbstractSession, ImperativeError, NextVerFeatures, ProcessUtils, Session } from "@zowe/imperative"; +import { AbstractSession, ImperativeError, ProcessUtils, Session } from "@zowe/imperative"; import { GetJobs } from "../../src"; import { GetJobsData } from "../__resources__/api/GetJobsData"; @@ -61,13 +61,6 @@ function mockGetJobsServerError(errorCode: string, causeErrors: string) { describe("GetJobs tests", () => { - beforeEach(() => { - /* This avoids having to mock ImperativeConfig.envVariablePrefix. - * Unless overridden, tests will use our legacy format for errors. - */ - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(false); - }); - describe("getStatus APIs", () => { it("should reject the promise when the server gets an error http code", async () => { @@ -211,20 +204,6 @@ describe("GetJobs tests", () => { }); it("should throw an error if more than one job is returned for a job id", async () => { - (ZosmfRestClient.getExpectJSON as any) = mockGetJobsJSONData([GetJobsData.SAMPLE_COMPLETE_JOB, GetJobsData.SAMPLE_ACTIVE_JOB]); - let err: Error | ImperativeError; - try { - await GetJobs.getJob(pretendSession, GetJobsData.SAMPLE_COMPLETE_JOB.jobid); - } catch (e) { - err = e; - } - expect(err).toBeDefined(); - expect(err instanceof ImperativeError).toEqual(true); - expect(err.message).toMatchSnapshot(); - }); - - it("should throw an error if more than one job is returned for a job id using V3_ERR_FORMAT", async () => { - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(true); (ZosmfRestClient.getExpectJSON as any) = mockGetJobsJSONData([GetJobsData.SAMPLE_COMPLETE_JOB, GetJobsData.SAMPLE_ACTIVE_JOB]); let err: Error | ImperativeError; try { @@ -242,20 +221,6 @@ describe("GetJobs tests", () => { }); it("should throw an error if zero jobs are returned when getting jobs by ID", async () => { - (ZosmfRestClient.getExpectJSON as any) = mockGetJobsJSONData([]); - let err: Error | ImperativeError; - try { - await GetJobs.getJob(pretendSession, GetJobsData.SAMPLE_COMPLETE_JOB.jobid); - } catch (e) { - err = e; - } - expect(err).toBeDefined(); - expect(err instanceof ImperativeError).toEqual(true); - expect(err.message).toMatchSnapshot(); - }); - - it("should throw an error if zero jobs are returned when getting jobs by ID using V3_ERR_FORMAT", async () => { - jest.spyOn(NextVerFeatures, "useV3ErrFormat").mockReturnValue(true); (ZosmfRestClient.getExpectJSON as any) = mockGetJobsJSONData([]); let err: Error | ImperativeError; try { diff --git a/packages/zosjobs/__tests__/__unit__/SearchJobs.unit.test.ts b/packages/zosjobs/__tests__/__unit__/SearchJobs.unit.test.ts new file mode 100644 index 0000000000..35cbedf278 --- /dev/null +++ b/packages/zosjobs/__tests__/__unit__/SearchJobs.unit.test.ts @@ -0,0 +1,74 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { ZosmfRestClient } from "@zowe/core-for-zowe-sdk"; +import { AbstractSession, IRestClientResponse, ProcessUtils, Session } from "@zowe/imperative"; +import { GetJobs, SearchJobs } from "../../src"; +import { GetJobsData } from "../__resources__/api/GetJobsData"; + +const pretendSession = new Session({user: "test", password: "test", hostname: "Test"}); + +function mockGetJobsJSONData(data: object) { + const mock = jest.fn((session: AbstractSession, resource: string, headers?: any[]): Promise => { + return new Promise((resolve, reject) => { + ProcessUtils.nextTick(() => { + resolve(data); + }); + }); + }); + return mock; +} + +function mockSearchJobsJSONData(data: object) { + const mock = jest.fn((session: AbstractSession, resource: string, headers?: any[]): Promise => { + return new Promise((resolve, reject) => { + ProcessUtils.nextTick(() => { + resolve(data); + }); + }); + }); + return mock; +} + +describe("SearchJobs tests", () => { + + describe("SearchJobs API successful call", () => { + it("should search a job and find the expected output", async () => { + const searchText:string = "BluhBluh"; + const request: IRestClientResponse = {dataString : searchText, requestSuccess : true, response : []}; + const headers = {'x-ibm-record-range': '1,1'}; + request.response.headers = headers; + (ZosmfRestClient.getExpectFullResponse as any) = mockSearchJobsJSONData(request); + (GetJobs.getJobsByPrefix as any) = mockGetJobsJSONData([GetJobsData.SAMPLE_COMPLETE_JOB, GetJobsData.SAMPLE_ACTIVE_JOB]); + (GetJobs.getSpoolFilesForJob as any) = mockGetJobsJSONData([GetJobsData.SAMPLE_COMPLETE_JOB]); + + const output = await SearchJobs.searchJobs(pretendSession, + {jobName: "testjob", searchString: searchText, searchLimit: 2, fileLimit: 2}); + expect(output).toMatchSnapshot(); + expect(output).toContain(searchText); + }); + }); + + describe("SearchJobs API failed call", () => { + it("should throw an exception for invalid parameters", async () => { + let err: any; + const errorText = "You must specify either the `--search-string` or `--search-regex` option"; + + try { + await SearchJobs.searchJobs(pretendSession, {jobName: "testjob"}); + } catch (e) { + err = e; + } + expect(err).toBeDefined(); + expect(err.message).toEqual(errorText); + }); + }); +}); diff --git a/packages/zosjobs/__tests__/__unit__/__snapshots__/GetJobs.unit.test.ts.snap b/packages/zosjobs/__tests__/__unit__/__snapshots__/GetJobs.unit.test.ts.snap index 3cf98b7b7a..a8c7fff252 100644 --- a/packages/zosjobs/__tests__/__unit__/__snapshots__/GetJobs.unit.test.ts.snap +++ b/packages/zosjobs/__tests__/__unit__/__snapshots__/GetJobs.unit.test.ts.snap @@ -1,10 +1,10 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`GetJobs tests getJcl APIs should be able to get JCL 1`] = `"//RUNMAIN JOB 105300000, JOB07172// USER=KELDA16//* test//EXEC EXEC PGM=IEFBR14,REGION=200M,MEMLIMIT=3G"`; +exports[`GetJobs tests getJcl APIs should be able to get JCL 1`] = `"//RUNMAIN JOB 105300000, JOB07172// USER=IBMUSER//* test//EXEC EXEC PGM=IEFBR14,REGION=200M,MEMLIMIT=3G"`; -exports[`GetJobs tests getJcl APIs should be able to get JCL 2`] = `"//RUNMAIN JOB 105300000, JOB07172// USER=KELDA16//* test//EXEC EXEC PGM=IEFBR14,REGION=200M,MEMLIMIT=3G"`; +exports[`GetJobs tests getJcl APIs should be able to get JCL 2`] = `"//RUNMAIN JOB 105300000, JOB07172// USER=IBMUSER//* test//EXEC EXEC PGM=IEFBR14,REGION=200M,MEMLIMIT=3G"`; -exports[`GetJobs tests getJcl APIs should be able to get JCL 3`] = `"//RUNMAIN JOB 105300000, JOB07172// USER=KELDA16//* test//EXEC EXEC PGM=IEFBR14,REGION=200M,MEMLIMIT=3G"`; +exports[`GetJobs tests getJcl APIs should be able to get JCL 3`] = `"//RUNMAIN JOB 105300000, JOB07172// USER=IBMUSER//* test//EXEC EXEC PGM=IEFBR14,REGION=200M,MEMLIMIT=3G"`; exports[`GetJobs tests getJcl APIs should error for missing jobname in callback scheme for jcl 1`] = `"Expect Error: Required parameter 'jobname' must not be blank"`; @@ -32,8 +32,8 @@ Array [ "files-url": "https://tso1:443/zosmf/restjobs/jobs/J0003781USILDAMDD3CE8146.......%3A/files", "job-correlator": "J0003781USILDAMDD3CE8146.......:", "jobid": "JOB03781", - "jobname": "KELDA16$", - "owner": "KELDA16", + "jobname": "IBMUSER$", + "owner": "IBMUSER", "phase": 130, "phase-name": "Job is actively converting", "retcode": null, @@ -67,8 +67,8 @@ Array [ "files-url": "https://tso1:443/zosmf/restjobs/jobs/J0003781USILDAMDD3CE8146.......%3A/files", "job-correlator": "J0003781USILDAMDD3CE8146.......:", "jobid": "JOB03781", - "jobname": "KELDA16$", - "owner": "KELDA16", + "jobname": "IBMUSER$", + "owner": "IBMUSER", "phase": 130, "phase-name": "Job is actively converting", "retcode": null, @@ -102,8 +102,8 @@ Array [ "files-url": "https://tso1:443/zosmf/restjobs/jobs/J0003781USILDAMDD3CE8146.......%3A/files", "job-correlator": "J0003781USILDAMDD3CE8146.......:", "jobid": "JOB03781", - "jobname": "KELDA16$", - "owner": "KELDA16", + "jobname": "IBMUSER$", + "owner": "IBMUSER", "phase": 130, "phase-name": "Job is actively converting", "retcode": null, @@ -137,8 +137,8 @@ Array [ "files-url": "https://tso1:443/zosmf/restjobs/jobs/J0003781USILDAMDD3CE8146.......%3A/files", "job-correlator": "J0003781USILDAMDD3CE8146.......:", "jobid": "JOB03781", - "jobname": "KELDA16$", - "owner": "KELDA16", + "jobname": "IBMUSER$", + "owner": "IBMUSER", "phase": 130, "phase-name": "Job is actively converting", "retcode": null, @@ -172,8 +172,8 @@ Array [ "files-url": "https://tso1:443/zosmf/restjobs/jobs/J0003781USILDAMDD3CE8146.......%3A/files", "job-correlator": "J0003781USILDAMDD3CE8146.......:", "jobid": "JOB03781", - "jobname": "KELDA16$", - "owner": "KELDA16", + "jobname": "IBMUSER$", + "owner": "IBMUSER", "phase": 130, "phase-name": "Job is actively converting", "retcode": null, @@ -207,8 +207,8 @@ Array [ "files-url": "https://tso1:443/zosmf/restjobs/jobs/J0003781USILDAMDD3CE8146.......%3A/files", "job-correlator": "J0003781USILDAMDD3CE8146.......:", "jobid": "JOB03781", - "jobname": "KELDA16$", - "owner": "KELDA16", + "jobname": "IBMUSER$", + "owner": "IBMUSER", "phase": 130, "phase-name": "Job is actively converting", "retcode": null, @@ -242,8 +242,8 @@ Array [ "files-url": "https://tso1:443/zosmf/restjobs/jobs/J0003781USILDAMDD3CE8146.......%3A/files", "job-correlator": "J0003781USILDAMDD3CE8146.......:", "jobid": "JOB03781", - "jobname": "KELDA16$", - "owner": "KELDA16", + "jobname": "IBMUSER$", + "owner": "IBMUSER", "phase": 130, "phase-name": "Job is actively converting", "retcode": null, @@ -277,8 +277,8 @@ Array [ "files-url": "https://tso1:443/zosmf/restjobs/jobs/J0003781USILDAMDD3CE8146.......%3A/files", "job-correlator": "J0003781USILDAMDD3CE8146.......:", "jobid": "JOB03781", - "jobname": "KELDA16$", - "owner": "KELDA16", + "jobname": "IBMUSER$", + "owner": "IBMUSER", "phase": 130, "phase-name": "Job is actively converting", "retcode": null, @@ -312,8 +312,8 @@ Array [ "files-url": "https://tso1:443/zosmf/restjobs/jobs/J0003781USILDAMDD3CE8146.......%3A/files", "job-correlator": "J0003781USILDAMDD3CE8146.......:", "jobid": "JOB03781", - "jobname": "KELDA16$", - "owner": "KELDA16", + "jobname": "IBMUSER$", + "owner": "IBMUSER", "phase": 130, "phase-name": "Job is actively converting", "retcode": null, @@ -347,8 +347,8 @@ Array [ "files-url": "https://tso1:443/zosmf/restjobs/jobs/J0003781USILDAMDD3CE8146.......%3A/files", "job-correlator": "J0003781USILDAMDD3CE8146.......:", "jobid": "JOB03781", - "jobname": "KELDA16$", - "owner": "KELDA16", + "jobname": "IBMUSER$", + "owner": "IBMUSER", "phase": 130, "phase-name": "Job is actively converting", "retcode": null, @@ -382,8 +382,8 @@ Array [ "files-url": "https://tso1:443/zosmf/restjobs/jobs/J0003781USILDAMDD3CE8146.......%3A/files", "job-correlator": "J0003781USILDAMDD3CE8146.......:", "jobid": "JOB03781", - "jobname": "KELDA16$", - "owner": "KELDA16", + "jobname": "IBMUSER$", + "owner": "IBMUSER", "phase": 130, "phase-name": "Job is actively converting", "retcode": null, @@ -441,10 +441,6 @@ exports[`GetJobs tests getJobs APIs should require prefix for getJobsByOwnerAndP exports[`GetJobs tests getJobs APIs should require prefix for getJobsByPrefix 1`] = `"Expect Error: Required parameter 'prefix' must not be blank"`; -exports[`GetJobs tests getJobs APIs should throw an error if more than one job is returned for a job id 1`] = `"Obtaining job info for a single job id TSUxxx on Test:443 failed: Expected 1 job returned but received 2"`; - -exports[`GetJobs tests getJobs APIs should throw an error if zero jobs are returned when getting jobs by ID 1`] = `"Obtaining job info for a single job id TSUxxx on Test:443 failed: Job not found"`; - exports[`GetJobs tests getJobsByParameters should get jobs even when no params are passed in 1`] = ` Array [ Object { @@ -467,8 +463,8 @@ Array [ "files-url": "https://tso1:443/zosmf/restjobs/jobs/J0003781USILDAMDD3CE8146.......%3A/files", "job-correlator": "J0003781USILDAMDD3CE8146.......:", "jobid": "JOB03781", - "jobname": "KELDA16$", - "owner": "KELDA16", + "jobname": "IBMUSER$", + "owner": "IBMUSER", "phase": 130, "phase-name": "Job is actively converting", "retcode": null, @@ -502,8 +498,8 @@ Array [ "files-url": "https://tso1:443/zosmf/restjobs/jobs/J0003781USILDAMDD3CE8146.......%3A/files", "job-correlator": "J0003781USILDAMDD3CE8146.......:", "jobid": "JOB03781", - "jobname": "KELDA16$", - "owner": "KELDA16", + "jobname": "IBMUSER$", + "owner": "IBMUSER", "phase": 130, "phase-name": "Job is actively converting", "retcode": null, @@ -515,17 +511,17 @@ Array [ ] `; -exports[`GetJobs tests getSpoolContent APIs should be able to get spool content 1`] = `" 1 J E S 2 J O B L O G -- S Y S T E M T E S T -- N O D E Z O W E T E S T 0 08.26.22 JOB01544 ---- MONDAY, 02 APR 2018 ---- 08.26.22 JOB01544 TSS7000I IBMUSER Last-Used 02 Apr 18 08:25 System=TEST Facility=TSO 08.26.22 JOB01544 TSS7001I Count=00411 Mode=Fail Locktime=None Name=ZOWE CLI TEST 08.26.22 JOB01544 $HASP373 RUNMAIN STARTED - WLM INIT - SRVCLASS BATSTWLM - SYS TEST 08.26.22 JOB01544 IEF403I RUNMAIN - STARTED - TIME=08.26.22 08.26.22 JOB01544 CAJR250I STEPNAME STEP PGM= CCODE EST-COST EXCPS ELAPSED TOT-CPU PAGE-IN PAGE-OT SWAP-IN SWAP-OT 08.26.22 JOB01544 CAJR251I EXEC 1 IEFBR14 0000 $ .00 0 00:00:00.00 00:00:00.00 0 0 0 0 08.26.22 JOB01544 IEF404I RUNMAIN - ENDED - TIME=08.26.22 08.26.22 JOB01544 CAJR252I JOB ENDED. TOTAL EST-COST $ .00 TOTAL CPU TIME 00:00:00.00 08.26.22 JOB01544 $HASP395 RUNMAIN ENDED - RC=00000------ JES2 JOB STATISTICS ------- 02 APR 2018 JOB EXECUTION DATE- 6 CARDS READ- 73 SYSOUT PRINT RECORDS- 0 SYSOUT PUNCH RECORDS- 8 SYSOUT SPOOL KBYTES- 0.00 MINUTES EXECUTION TIME"`; +exports[`GetJobs tests getSpoolContent APIs should be able to get spool content 1`] = `" 1 J E S 2 J O B L O G -- S Y S T E M T E S T -- N O D E Z O W E T E S T 0 08.26.22 JOB01544 ---- MONDAY, 02 APR 2018 ---- 08.26.22 JOB01544 TSS7000I IBMUSER Last-Used 02 Apr 18 08:25 System=TEST Facility=TSO 08.26.22 JOB01544 TSS7001I Count=00411 Mode=Fail Locktime=None Name=USER, IBM 08.26.22 JOB01544 $HASP373 RUNMAIN STARTED - WLM INIT - SRVCLASS BATSTWLM - SYS TEST 08.26.22 JOB01544 IEF403I RUNMAIN - STARTED - TIME=08.26.22 08.26.22 JOB01544 CAJR250I STEPNAME STEP PGM= CCODE EST-COST EXCPS ELAPSED TOT-CPU PAGE-IN PAGE-OT SWAP-IN SWAP-OT 08.26.22 JOB01544 CAJR251I EXEC 1 IEFBR14 0000 $ .00 0 00:00:00.00 00:00:00.00 0 0 0 0 08.26.22 JOB01544 IEF404I RUNMAIN - ENDED - TIME=08.26.22 08.26.22 JOB01544 CAJR252I JOB ENDED. TOTAL EST-COST $ .00 TOTAL CPU TIME 00:00:00.00 08.26.22 JOB01544 $HASP395 RUNMAIN ENDED - RC=00000------ JES2 JOB STATISTICS ------- 02 APR 2018 JOB EXECUTION DATE- 6 CARDS READ- 73 SYSOUT PRINT RECORDS- 0 SYSOUT PUNCH RECORDS- 8 SYSOUT SPOOL KBYTES- 0.00 MINUTES EXECUTION TIME"`; -exports[`GetJobs tests getSpoolContent APIs should be able to get spool content 2`] = `" 1 J E S 2 J O B L O G -- S Y S T E M T E S T -- N O D E Z O W E T E S T 0 08.26.22 JOB01544 ---- MONDAY, 02 APR 2018 ---- 08.26.22 JOB01544 TSS7000I IBMUSER Last-Used 02 Apr 18 08:25 System=TEST Facility=TSO 08.26.22 JOB01544 TSS7001I Count=00411 Mode=Fail Locktime=None Name=ZOWE CLI TEST 08.26.22 JOB01544 $HASP373 RUNMAIN STARTED - WLM INIT - SRVCLASS BATSTWLM - SYS TEST 08.26.22 JOB01544 IEF403I RUNMAIN - STARTED - TIME=08.26.22 08.26.22 JOB01544 CAJR250I STEPNAME STEP PGM= CCODE EST-COST EXCPS ELAPSED TOT-CPU PAGE-IN PAGE-OT SWAP-IN SWAP-OT 08.26.22 JOB01544 CAJR251I EXEC 1 IEFBR14 0000 $ .00 0 00:00:00.00 00:00:00.00 0 0 0 0 08.26.22 JOB01544 IEF404I RUNMAIN - ENDED - TIME=08.26.22 08.26.22 JOB01544 CAJR252I JOB ENDED. TOTAL EST-COST $ .00 TOTAL CPU TIME 00:00:00.00 08.26.22 JOB01544 $HASP395 RUNMAIN ENDED - RC=00000------ JES2 JOB STATISTICS ------- 02 APR 2018 JOB EXECUTION DATE- 6 CARDS READ- 73 SYSOUT PRINT RECORDS- 0 SYSOUT PUNCH RECORDS- 8 SYSOUT SPOOL KBYTES- 0.00 MINUTES EXECUTION TIME"`; +exports[`GetJobs tests getSpoolContent APIs should be able to get spool content 2`] = `" 1 J E S 2 J O B L O G -- S Y S T E M T E S T -- N O D E Z O W E T E S T 0 08.26.22 JOB01544 ---- MONDAY, 02 APR 2018 ---- 08.26.22 JOB01544 TSS7000I IBMUSER Last-Used 02 Apr 18 08:25 System=TEST Facility=TSO 08.26.22 JOB01544 TSS7001I Count=00411 Mode=Fail Locktime=None Name=USER, IBM 08.26.22 JOB01544 $HASP373 RUNMAIN STARTED - WLM INIT - SRVCLASS BATSTWLM - SYS TEST 08.26.22 JOB01544 IEF403I RUNMAIN - STARTED - TIME=08.26.22 08.26.22 JOB01544 CAJR250I STEPNAME STEP PGM= CCODE EST-COST EXCPS ELAPSED TOT-CPU PAGE-IN PAGE-OT SWAP-IN SWAP-OT 08.26.22 JOB01544 CAJR251I EXEC 1 IEFBR14 0000 $ .00 0 00:00:00.00 00:00:00.00 0 0 0 0 08.26.22 JOB01544 IEF404I RUNMAIN - ENDED - TIME=08.26.22 08.26.22 JOB01544 CAJR252I JOB ENDED. TOTAL EST-COST $ .00 TOTAL CPU TIME 00:00:00.00 08.26.22 JOB01544 $HASP395 RUNMAIN ENDED - RC=00000------ JES2 JOB STATISTICS ------- 02 APR 2018 JOB EXECUTION DATE- 6 CARDS READ- 73 SYSOUT PRINT RECORDS- 0 SYSOUT PUNCH RECORDS- 8 SYSOUT SPOOL KBYTES- 0.00 MINUTES EXECUTION TIME"`; -exports[`GetJobs tests getSpoolContent APIs should be able to get spool content with empty encoding 1`] = `" 1 J E S 2 J O B L O G -- S Y S T E M T E S T -- N O D E Z O W E T E S T 0 08.26.22 JOB01544 ---- MONDAY, 02 APR 2018 ---- 08.26.22 JOB01544 TSS7000I IBMUSER Last-Used 02 Apr 18 08:25 System=TEST Facility=TSO 08.26.22 JOB01544 TSS7001I Count=00411 Mode=Fail Locktime=None Name=ZOWE CLI TEST 08.26.22 JOB01544 $HASP373 RUNMAIN STARTED - WLM INIT - SRVCLASS BATSTWLM - SYS TEST 08.26.22 JOB01544 IEF403I RUNMAIN - STARTED - TIME=08.26.22 08.26.22 JOB01544 CAJR250I STEPNAME STEP PGM= CCODE EST-COST EXCPS ELAPSED TOT-CPU PAGE-IN PAGE-OT SWAP-IN SWAP-OT 08.26.22 JOB01544 CAJR251I EXEC 1 IEFBR14 0000 $ .00 0 00:00:00.00 00:00:00.00 0 0 0 0 08.26.22 JOB01544 IEF404I RUNMAIN - ENDED - TIME=08.26.22 08.26.22 JOB01544 CAJR252I JOB ENDED. TOTAL EST-COST $ .00 TOTAL CPU TIME 00:00:00.00 08.26.22 JOB01544 $HASP395 RUNMAIN ENDED - RC=00000------ JES2 JOB STATISTICS ------- 02 APR 2018 JOB EXECUTION DATE- 6 CARDS READ- 73 SYSOUT PRINT RECORDS- 0 SYSOUT PUNCH RECORDS- 8 SYSOUT SPOOL KBYTES- 0.00 MINUTES EXECUTION TIME"`; +exports[`GetJobs tests getSpoolContent APIs should be able to get spool content with empty encoding 1`] = `" 1 J E S 2 J O B L O G -- S Y S T E M T E S T -- N O D E Z O W E T E S T 0 08.26.22 JOB01544 ---- MONDAY, 02 APR 2018 ---- 08.26.22 JOB01544 TSS7000I IBMUSER Last-Used 02 Apr 18 08:25 System=TEST Facility=TSO 08.26.22 JOB01544 TSS7001I Count=00411 Mode=Fail Locktime=None Name=USER, IBM 08.26.22 JOB01544 $HASP373 RUNMAIN STARTED - WLM INIT - SRVCLASS BATSTWLM - SYS TEST 08.26.22 JOB01544 IEF403I RUNMAIN - STARTED - TIME=08.26.22 08.26.22 JOB01544 CAJR250I STEPNAME STEP PGM= CCODE EST-COST EXCPS ELAPSED TOT-CPU PAGE-IN PAGE-OT SWAP-IN SWAP-OT 08.26.22 JOB01544 CAJR251I EXEC 1 IEFBR14 0000 $ .00 0 00:00:00.00 00:00:00.00 0 0 0 0 08.26.22 JOB01544 IEF404I RUNMAIN - ENDED - TIME=08.26.22 08.26.22 JOB01544 CAJR252I JOB ENDED. TOTAL EST-COST $ .00 TOTAL CPU TIME 00:00:00.00 08.26.22 JOB01544 $HASP395 RUNMAIN ENDED - RC=00000------ JES2 JOB STATISTICS ------- 02 APR 2018 JOB EXECUTION DATE- 6 CARDS READ- 73 SYSOUT PRINT RECORDS- 0 SYSOUT PUNCH RECORDS- 8 SYSOUT SPOOL KBYTES- 0.00 MINUTES EXECUTION TIME"`; -exports[`GetJobs tests getSpoolContent APIs should be able to get spool content with empty encoding 2`] = `" 1 J E S 2 J O B L O G -- S Y S T E M T E S T -- N O D E Z O W E T E S T 0 08.26.22 JOB01544 ---- MONDAY, 02 APR 2018 ---- 08.26.22 JOB01544 TSS7000I IBMUSER Last-Used 02 Apr 18 08:25 System=TEST Facility=TSO 08.26.22 JOB01544 TSS7001I Count=00411 Mode=Fail Locktime=None Name=ZOWE CLI TEST 08.26.22 JOB01544 $HASP373 RUNMAIN STARTED - WLM INIT - SRVCLASS BATSTWLM - SYS TEST 08.26.22 JOB01544 IEF403I RUNMAIN - STARTED - TIME=08.26.22 08.26.22 JOB01544 CAJR250I STEPNAME STEP PGM= CCODE EST-COST EXCPS ELAPSED TOT-CPU PAGE-IN PAGE-OT SWAP-IN SWAP-OT 08.26.22 JOB01544 CAJR251I EXEC 1 IEFBR14 0000 $ .00 0 00:00:00.00 00:00:00.00 0 0 0 0 08.26.22 JOB01544 IEF404I RUNMAIN - ENDED - TIME=08.26.22 08.26.22 JOB01544 CAJR252I JOB ENDED. TOTAL EST-COST $ .00 TOTAL CPU TIME 00:00:00.00 08.26.22 JOB01544 $HASP395 RUNMAIN ENDED - RC=00000------ JES2 JOB STATISTICS ------- 02 APR 2018 JOB EXECUTION DATE- 6 CARDS READ- 73 SYSOUT PRINT RECORDS- 0 SYSOUT PUNCH RECORDS- 8 SYSOUT SPOOL KBYTES- 0.00 MINUTES EXECUTION TIME"`; +exports[`GetJobs tests getSpoolContent APIs should be able to get spool content with empty encoding 2`] = `" 1 J E S 2 J O B L O G -- S Y S T E M T E S T -- N O D E Z O W E T E S T 0 08.26.22 JOB01544 ---- MONDAY, 02 APR 2018 ---- 08.26.22 JOB01544 TSS7000I IBMUSER Last-Used 02 Apr 18 08:25 System=TEST Facility=TSO 08.26.22 JOB01544 TSS7001I Count=00411 Mode=Fail Locktime=None Name=USER, IBM 08.26.22 JOB01544 $HASP373 RUNMAIN STARTED - WLM INIT - SRVCLASS BATSTWLM - SYS TEST 08.26.22 JOB01544 IEF403I RUNMAIN - STARTED - TIME=08.26.22 08.26.22 JOB01544 CAJR250I STEPNAME STEP PGM= CCODE EST-COST EXCPS ELAPSED TOT-CPU PAGE-IN PAGE-OT SWAP-IN SWAP-OT 08.26.22 JOB01544 CAJR251I EXEC 1 IEFBR14 0000 $ .00 0 00:00:00.00 00:00:00.00 0 0 0 0 08.26.22 JOB01544 IEF404I RUNMAIN - ENDED - TIME=08.26.22 08.26.22 JOB01544 CAJR252I JOB ENDED. TOTAL EST-COST $ .00 TOTAL CPU TIME 00:00:00.00 08.26.22 JOB01544 $HASP395 RUNMAIN ENDED - RC=00000------ JES2 JOB STATISTICS ------- 02 APR 2018 JOB EXECUTION DATE- 6 CARDS READ- 73 SYSOUT PRINT RECORDS- 0 SYSOUT PUNCH RECORDS- 8 SYSOUT SPOOL KBYTES- 0.00 MINUTES EXECUTION TIME"`; -exports[`GetJobs tests getSpoolContent APIs should be able to get spool content with encoding 1`] = `" 1 J E S 2 J O B L O G -- S Y S T E M T E S T -- N O D E Z O W E T E S T 0 08.26.22 JOB01544 ---- MONDAY, 02 APR 2018 ---- 08.26.22 JOB01544 TSS7000I IBMUSER Last-Used 02 Apr 18 08:25 System=TEST Facility=TSO 08.26.22 JOB01544 TSS7001I Count=00411 Mode=Fail Locktime=None Name=ZOWE CLI TEST 08.26.22 JOB01544 $HASP373 RUNMAIN STARTED - WLM INIT - SRVCLASS BATSTWLM - SYS TEST 08.26.22 JOB01544 IEF403I RUNMAIN - STARTED - TIME=08.26.22 08.26.22 JOB01544 CAJR250I STEPNAME STEP PGM= CCODE EST-COST EXCPS ELAPSED TOT-CPU PAGE-IN PAGE-OT SWAP-IN SWAP-OT 08.26.22 JOB01544 CAJR251I EXEC 1 IEFBR14 0000 $ .00 0 00:00:00.00 00:00:00.00 0 0 0 0 08.26.22 JOB01544 IEF404I RUNMAIN - ENDED - TIME=08.26.22 08.26.22 JOB01544 CAJR252I JOB ENDED. TOTAL EST-COST $ .00 TOTAL CPU TIME 00:00:00.00 08.26.22 JOB01544 $HASP395 RUNMAIN ENDED - RC=00000------ JES2 JOB STATISTICS ------- 02 APR 2018 JOB EXECUTION DATE- 6 CARDS READ- 73 SYSOUT PRINT RECORDS- 0 SYSOUT PUNCH RECORDS- 8 SYSOUT SPOOL KBYTES- 0.00 MINUTES EXECUTION TIME"`; +exports[`GetJobs tests getSpoolContent APIs should be able to get spool content with encoding 1`] = `" 1 J E S 2 J O B L O G -- S Y S T E M T E S T -- N O D E Z O W E T E S T 0 08.26.22 JOB01544 ---- MONDAY, 02 APR 2018 ---- 08.26.22 JOB01544 TSS7000I IBMUSER Last-Used 02 Apr 18 08:25 System=TEST Facility=TSO 08.26.22 JOB01544 TSS7001I Count=00411 Mode=Fail Locktime=None Name=USER, IBM 08.26.22 JOB01544 $HASP373 RUNMAIN STARTED - WLM INIT - SRVCLASS BATSTWLM - SYS TEST 08.26.22 JOB01544 IEF403I RUNMAIN - STARTED - TIME=08.26.22 08.26.22 JOB01544 CAJR250I STEPNAME STEP PGM= CCODE EST-COST EXCPS ELAPSED TOT-CPU PAGE-IN PAGE-OT SWAP-IN SWAP-OT 08.26.22 JOB01544 CAJR251I EXEC 1 IEFBR14 0000 $ .00 0 00:00:00.00 00:00:00.00 0 0 0 0 08.26.22 JOB01544 IEF404I RUNMAIN - ENDED - TIME=08.26.22 08.26.22 JOB01544 CAJR252I JOB ENDED. TOTAL EST-COST $ .00 TOTAL CPU TIME 00:00:00.00 08.26.22 JOB01544 $HASP395 RUNMAIN ENDED - RC=00000------ JES2 JOB STATISTICS ------- 02 APR 2018 JOB EXECUTION DATE- 6 CARDS READ- 73 SYSOUT PRINT RECORDS- 0 SYSOUT PUNCH RECORDS- 8 SYSOUT SPOOL KBYTES- 0.00 MINUTES EXECUTION TIME"`; -exports[`GetJobs tests getSpoolContent APIs should be able to get spool content with encoding 2`] = `" 1 J E S 2 J O B L O G -- S Y S T E M T E S T -- N O D E Z O W E T E S T 0 08.26.22 JOB01544 ---- MONDAY, 02 APR 2018 ---- 08.26.22 JOB01544 TSS7000I IBMUSER Last-Used 02 Apr 18 08:25 System=TEST Facility=TSO 08.26.22 JOB01544 TSS7001I Count=00411 Mode=Fail Locktime=None Name=ZOWE CLI TEST 08.26.22 JOB01544 $HASP373 RUNMAIN STARTED - WLM INIT - SRVCLASS BATSTWLM - SYS TEST 08.26.22 JOB01544 IEF403I RUNMAIN - STARTED - TIME=08.26.22 08.26.22 JOB01544 CAJR250I STEPNAME STEP PGM= CCODE EST-COST EXCPS ELAPSED TOT-CPU PAGE-IN PAGE-OT SWAP-IN SWAP-OT 08.26.22 JOB01544 CAJR251I EXEC 1 IEFBR14 0000 $ .00 0 00:00:00.00 00:00:00.00 0 0 0 0 08.26.22 JOB01544 IEF404I RUNMAIN - ENDED - TIME=08.26.22 08.26.22 JOB01544 CAJR252I JOB ENDED. TOTAL EST-COST $ .00 TOTAL CPU TIME 00:00:00.00 08.26.22 JOB01544 $HASP395 RUNMAIN ENDED - RC=00000------ JES2 JOB STATISTICS ------- 02 APR 2018 JOB EXECUTION DATE- 6 CARDS READ- 73 SYSOUT PRINT RECORDS- 0 SYSOUT PUNCH RECORDS- 8 SYSOUT SPOOL KBYTES- 0.00 MINUTES EXECUTION TIME"`; +exports[`GetJobs tests getSpoolContent APIs should be able to get spool content with encoding 2`] = `" 1 J E S 2 J O B L O G -- S Y S T E M T E S T -- N O D E Z O W E T E S T 0 08.26.22 JOB01544 ---- MONDAY, 02 APR 2018 ---- 08.26.22 JOB01544 TSS7000I IBMUSER Last-Used 02 Apr 18 08:25 System=TEST Facility=TSO 08.26.22 JOB01544 TSS7001I Count=00411 Mode=Fail Locktime=None Name=USER, IBM 08.26.22 JOB01544 $HASP373 RUNMAIN STARTED - WLM INIT - SRVCLASS BATSTWLM - SYS TEST 08.26.22 JOB01544 IEF403I RUNMAIN - STARTED - TIME=08.26.22 08.26.22 JOB01544 CAJR250I STEPNAME STEP PGM= CCODE EST-COST EXCPS ELAPSED TOT-CPU PAGE-IN PAGE-OT SWAP-IN SWAP-OT 08.26.22 JOB01544 CAJR251I EXEC 1 IEFBR14 0000 $ .00 0 00:00:00.00 00:00:00.00 0 0 0 0 08.26.22 JOB01544 IEF404I RUNMAIN - ENDED - TIME=08.26.22 08.26.22 JOB01544 CAJR252I JOB ENDED. TOTAL EST-COST $ .00 TOTAL CPU TIME 00:00:00.00 08.26.22 JOB01544 $HASP395 RUNMAIN ENDED - RC=00000------ JES2 JOB STATISTICS ------- 02 APR 2018 JOB EXECUTION DATE- 6 CARDS READ- 73 SYSOUT PRINT RECORDS- 0 SYSOUT PUNCH RECORDS- 8 SYSOUT SPOOL KBYTES- 0.00 MINUTES EXECUTION TIME"`; exports[`GetJobs tests getSpoolContent APIs should error for missing jobname in callback scheme for spool content 1`] = `"Expect Error: Required job file object must be defined"`; diff --git a/packages/zosjobs/__tests__/__unit__/__snapshots__/SearchJobs.unit.test.ts.snap b/packages/zosjobs/__tests__/__unit__/__snapshots__/SearchJobs.unit.test.ts.snap new file mode 100644 index 0000000000..66b4cd6742 --- /dev/null +++ b/packages/zosjobs/__tests__/__unit__/__snapshots__/SearchJobs.unit.test.ts.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SearchJobs tests SearchJobs API successful call should search a job and find the expected output 1`] = ` +"Job Name: IBMUSER$ Job Id: TSUxxx Spool file: undefined(ID #undefined Step: undefined) + Line 2 : BluhBluh Line 2 : BluhBluh +Job Name: IBMUSER$ Job Id: JOB03781 Spool file: undefined(ID #undefined Step: undefined) + Line 2 : BluhBluh Line 2 : BluhBluh +" +`; diff --git a/packages/zosjobs/package.json b/packages/zosjobs/package.json index 7496c68cc9..3656b6955b 100644 --- a/packages/zosjobs/package.json +++ b/packages/zosjobs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-jobs-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "description": "Zowe SDK to interact with jobs on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -46,15 +46,18 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "7.29.2" + "@zowe/zos-files-for-zowe-sdk": "8.0.0-next.202409111528" }, "devDependencies": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" }, "peerDependencies": { - "@zowe/core-for-zowe-sdk": "^7.0.0", - "@zowe/imperative": "^5.0.0" + "@zowe/core-for-zowe-sdk": "^8.0.0-next", + "@zowe/imperative": "^8.0.0-next" + }, + "engines": { + "node": ">=18.12.0" } } diff --git a/packages/zosjobs/src/CancelJobs.ts b/packages/zosjobs/src/CancelJobs.ts index c7b0dd7cb8..4836757bf4 100644 --- a/packages/zosjobs/src/CancelJobs.ts +++ b/packages/zosjobs/src/CancelJobs.ts @@ -93,7 +93,7 @@ export class CancelJobs { /** - * Getter for brightside logger + * Getter for Zowe logger * @returns {Logger} */ private static get log(): Logger { diff --git a/packages/zosjobs/src/DeleteJobs.ts b/packages/zosjobs/src/DeleteJobs.ts index fa9afbee52..15030304e0 100644 --- a/packages/zosjobs/src/DeleteJobs.ts +++ b/packages/zosjobs/src/DeleteJobs.ts @@ -9,7 +9,8 @@ * */ -import { AbstractSession, ImperativeExpect, IO, Logger } from "@zowe/imperative"; +import * as path from "path"; +import { AbstractSession, ImperativeExpect, Logger } from "@zowe/imperative"; import { JobsConstants } from "./JobsConstants"; import { ZosmfHeaders, ZosmfRestClient } from "@zowe/core-for-zowe-sdk"; import { IJob } from "./doc/response/IJob"; @@ -75,7 +76,7 @@ export class DeleteJobs { headers.push(ZosmfHeaders.X_IBM_JOB_MODIFY_VERSION_2); } - const parameters: string = IO.FILE_DELIM + encodeURIComponent(parms.jobname) + IO.FILE_DELIM + encodeURIComponent(parms.jobid); + const parameters: string = path.posix.sep + encodeURIComponent(parms.jobname) + path.posix.sep + encodeURIComponent(parms.jobid); const responseJson = await ZosmfRestClient.deleteExpectJSON(session, JobsConstants.RESOURCE + parameters, headers); if (parms.modifyVersion === "2.0") { @@ -88,7 +89,7 @@ export class DeleteJobs { /** - * Getter for brightside logger + * Getter for Zowe logger * @returns {Logger} */ private static get log(): Logger { diff --git a/packages/zosjobs/src/DownloadJobs.ts b/packages/zosjobs/src/DownloadJobs.ts index 679ad2ad5a..b305d05394 100644 --- a/packages/zosjobs/src/DownloadJobs.ts +++ b/packages/zosjobs/src/DownloadJobs.ts @@ -9,7 +9,8 @@ * */ -import { AbstractSession, Headers, ImperativeExpect, IO, Logger } from "@zowe/imperative"; +import * as path from "path"; +import { AbstractSession, ImperativeExpect, IO, Logger, Headers } from "@zowe/imperative"; import { JobsConstants } from "./JobsConstants"; import { IDownloadAllSpoolContentParms } from "./doc/input/IDownloadAllSpoolContentParms"; import { IJobFile } from "./doc/response/IJobFile"; @@ -131,35 +132,6 @@ export class DownloadJobs { true); } - /** - * Get the file where a specified spool file (IJobFile) would be downloaded to - * @deprecated Use getSpoolDownloadFilePath instead - * @static - * @param {IJobFile} jobFile - the spool file that would be downloaded - * @param {boolean} omitJobidDirectory - if true, the job ID of the jobFile will not be included in the file path - * @param {string} outDir - parent output directory you would like to download to - * @returns {string} the file path that the spool file would be downloaded to - * @memberof DownloadJobs - */ - public static getSpoolDownloadFile(jobFile: IJobFile, omitJobidDirectory?: boolean, outDir = DownloadJobs.DEFAULT_JOBS_OUTPUT_DIR): string { - this.log.trace("getSpoolDownloadFile called with jobFile %s, omitJobIDDirectory: %s, outDir: %s", - JSON.stringify(jobFile), omitJobidDirectory + "", outDir); - let directory: string = outDir; - if (omitJobidDirectory == null || omitJobidDirectory === false) { - directory += IO.FILE_DELIM + jobFile.jobid; - } - - if (jobFile.procstep != null) { - directory += IO.FILE_DELIM + jobFile.procstep; - } - - if (jobFile.stepname != null) { - directory += IO.FILE_DELIM + jobFile.stepname; - } - - return directory + IO.FILE_DELIM + jobFile.ddname + DownloadJobs.DEFAULT_JOBS_OUTPUT_FILE_EXT; - } - /** * Get the file where a specified spool file (IJobFile) would be downloaded to * @static @@ -168,30 +140,30 @@ export class DownloadJobs { * @memberof DownloadJobs */ public static getSpoolDownloadFilePath(parms: IDownloadSpoolContentParms): string { - this.log.trace("getSpoolDownloadFile called with jobFile %s, omitJobIDDirectory: %s, outDir: %s", + this.log.trace("getSpoolDownloadFilePath called with jobFile %s, omitJobIDDirectory: %s, outDir: %s", JSON.stringify(parms.jobFile), parms.omitJobidDirectory + "", parms.outDir); let directory: string = parms.outDir ?? DownloadJobs.DEFAULT_JOBS_OUTPUT_DIR; if (parms.omitJobidDirectory == null || parms.omitJobidDirectory === false) { - directory += IO.FILE_DELIM + parms.jobFile.jobid; + directory += path.posix.sep + parms.jobFile.jobid; } if (parms.jobFile.procstep != null) { - directory += IO.FILE_DELIM + parms.jobFile.procstep; + directory += path.posix.sep + parms.jobFile.procstep; } if (parms.jobFile.stepname != null) { - directory += IO.FILE_DELIM + parms.jobFile.stepname; + directory += path.posix.sep + parms.jobFile.stepname; } const extension = parms.extension ?? DownloadJobs.DEFAULT_JOBS_OUTPUT_FILE_EXT; - return directory + IO.FILE_DELIM + parms.jobFile.ddname + extension; + return directory + path.posix.sep + parms.jobFile.ddname + extension; } /** - * Getter for brightside logger + * Getter for Zowe logger * @returns {Logger} */ private static get log(): Logger { diff --git a/packages/zosjobs/src/GetJobs.ts b/packages/zosjobs/src/GetJobs.ts index abd449e911..5cefdfc953 100644 --- a/packages/zosjobs/src/GetJobs.ts +++ b/packages/zosjobs/src/GetJobs.ts @@ -9,7 +9,7 @@ * */ -import { AbstractSession, Headers, ImperativeError, ImperativeExpect, Logger, NextVerFeatures, RestClient } from "@zowe/imperative"; +import { AbstractSession, Headers, ImperativeError, ImperativeExpect, Logger, RestClient } from "@zowe/imperative"; import { JobsConstants } from "./JobsConstants"; import { ZosmfRestClient } from "@zowe/core-for-zowe-sdk"; import { ICommonJobParms, IGetJobsParms, IJob, IJobFile } from "./"; @@ -109,10 +109,6 @@ export class GetJobs { ImperativeExpect.toNotBeNullOrUndefined(session, "Required session must be defined"); const jobs = await GetJobs.getJobsCommon(session, { jobid, owner: "*" }); - // TODO:V3_ERR_FORMAT - Remove in V3 - const errorMessagePrefix: string = "Obtaining job info for a single job id " + jobid + " on " + - session.ISession.hostname + ":" + session.ISession.port + " failed: "; - const userMsg: string = "Cannot obtain job info for job id = " + jobid; const diagInfo: string = "Protocol: " + session.ISession.protocol + @@ -124,34 +120,20 @@ export class GetJobs { // fail if no jobs if (jobs.length === 0) { - // TODO:V3_ERR_FORMAT - Don't test for env variable in V3 - if (NextVerFeatures.useV3ErrFormat()) { - throw new ImperativeError({ - msg: userMsg, - causeErrors: "Zero jobs were returned.", - additionalDetails: diagInfo - }); - } else { // TODO:V3_ERR_FORMAT - Remove in V3 - throw new ImperativeError({ - msg: errorMessagePrefix + "Job not found" - }); - } + throw new ImperativeError({ + msg: userMsg, + causeErrors: "Zero jobs were returned.", + additionalDetails: diagInfo + }); } // fail if unexpected number of jobs (job id should be unique) if (jobs.length > 1) { - // TODO:V3_ERR_FORMAT - Don't test for env variable in V3 - if (NextVerFeatures.useV3ErrFormat()) { - throw new ImperativeError({ - msg: userMsg, - causeErrors: jobs.length + " jobs were returned. Only expected 1.", - additionalDetails: diagInfo - }); - } else { // TODO:V3_ERR_FORMAT - Remove in V3 - throw new ImperativeError({ - msg: errorMessagePrefix + "Expected 1 job returned but received " + jobs.length - }); - } + throw new ImperativeError({ + msg: userMsg, + causeErrors: jobs.length + " jobs were returned. Only expected 1.", + additionalDetails: diagInfo + }); } // return the single job @@ -174,7 +156,7 @@ export class GetJobs { if (params) { if (params.owner) { - query += (JobsConstants.QUERY_OWNER + encodeURIComponent(params.owner)); + query += JobsConstants.QUERY_OWNER + encodeURIComponent(params.owner); } if (params.prefix) { if (params.prefix !== JobsConstants.DEFAULT_PREFIX) { @@ -189,31 +171,31 @@ export class GetJobs { if (RestClient.hasQueryString(query)) { query += JobsConstants.COMBO_ID; } - query += (JobsConstants.QUERY_MAX_JOBS + encodeURIComponent(params.maxJobs)); + query += JobsConstants.QUERY_MAX_JOBS + encodeURIComponent(params.maxJobs); } } if (params.jobid) { if (RestClient.hasQueryString(query)) { query += JobsConstants.COMBO_ID; } - query += (JobsConstants.QUERY_JOBID + encodeURIComponent(params.jobid)); + query += JobsConstants.QUERY_JOBID + encodeURIComponent(params.jobid); } if (params.execData) { if (RestClient.hasQueryString(query)) { query += JobsConstants.COMBO_ID; } - query += (JobsConstants.EXEC_DATA); + query += JobsConstants.EXEC_DATA; } if (params.status) { if (RestClient.hasQueryString(query)) { query += JobsConstants.COMBO_ID; } - query += (JobsConstants.QUERY_STATUS + encodeURIComponent(params.status)); + query += JobsConstants.QUERY_STATUS + encodeURIComponent(params.status); } } let resource = JobsConstants.RESOURCE; - resource += (query === JobsConstants.QUERY_ID) ? "" : query; + resource += query === JobsConstants.QUERY_ID ? "" : query; Logger.getAppLogger().info("GetJobs.getJobsCommon() resource: " + resource); const jobs = await ZosmfRestClient.getExpectJSON(session, resource); diff --git a/packages/zosjobs/src/JobsMessages.ts b/packages/zosjobs/src/JobsMessages.ts index 1d4429a9ab..0eec22f2e3 100644 --- a/packages/zosjobs/src/JobsMessages.ts +++ b/packages/zosjobs/src/JobsMessages.ts @@ -41,5 +41,21 @@ export const ZosJobsMessages: { [key: string]: IMessageDefinition } = { */ missingJcl: { message: "No JCL provided" + }, + + /** + * Message indicating that no search option was passed or both were passed + * @memberof ZosJobsMessages + * @type {IMessageDefinition} + */ + missingSearchOption: { + message: "You must specify either the `--search-string` or `--search-regex` option" + }, + + /** + * Message indicating that a failure has happened in the NodeJS File System API + */ + nodeJsFsError: { + message: "Node.js File System API error" } }; diff --git a/packages/zosjobs/src/MonitorJobs.ts b/packages/zosjobs/src/MonitorJobs.ts index 4781b43a66..5595dd0ba9 100644 --- a/packages/zosjobs/src/MonitorJobs.ts +++ b/packages/zosjobs/src/MonitorJobs.ts @@ -160,7 +160,7 @@ export class MonitorJobs { } /** - * Obtain an instance of the app logger (Brightside). + * Obtain an instance of the app logger (Zowe). * @private * @static * @type {Logger} diff --git a/packages/zosjobs/src/SearchJobs.ts b/packages/zosjobs/src/SearchJobs.ts new file mode 100644 index 0000000000..de73ac4bed --- /dev/null +++ b/packages/zosjobs/src/SearchJobs.ts @@ -0,0 +1,163 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +import { AbstractSession, ImperativeError, IRestClientResponse, IOptionsFullResponse, Headers, Logger} from "@zowe/imperative"; +import { ZosmfRestClient, ZosmfHeaders } from "@zowe/core-for-zowe-sdk"; +import { GetJobs} from "./GetJobs"; +import { ISearchJobsParms } from "./doc/input/ISearchJobsParms"; +import { IJobFile } from "./doc/response/IJobFile"; +import { IJob } from "./doc/response/IJob"; +import { JobsConstants } from "./JobsConstants"; +import { ZosJobsMessages } from "./JobsMessages"; + +/** + * Class to handle the searching of z/OS batch job spool output + * @export + * @class SearchJobs + */ +export class SearchJobs { + /** + * Search Jobs - Search the spool output of the specified job name for a string or regular expression + * @static + * @param {AbstractSession} session - z/OSMF connection info + * @param {ISearchJobsParms} searchParms - The search parameters for the API call + * @returns {Promise} - promise that resolves to spool output + * @throws {ImperativeError} --search-string or --search-regx must be specified + * @memberof searchJobs + */ + public static async searchJobs(session: AbstractSession, searchParms : ISearchJobsParms) { + const jobName: string = searchParms.jobName; + const searchString: string= searchParms.searchString; + const searchRegex: string = searchParms.searchRegex; + const caseInsensitive: boolean = searchParms.caseInsensitive; + const searchLimit: number = searchParms.searchLimit; + const fileLimit: number = searchParms.fileLimit; + + Logger.getAppLogger().info("SearchJobs.searchJobs() called!"); + let replyBuffer:string = ""; + + // Validate that a search string or regex parameter was passed + if(searchRegex === undefined && searchString === undefined){ + throw new ImperativeError({ msg: ZosJobsMessages.missingSearchOption.message }); + } + + // Validate that both options are not passed on the same call + if(searchRegex !== undefined && searchString !== undefined){ + throw new ImperativeError({ msg: ZosJobsMessages.missingSearchOption.message }); + } + + // Loop through all of the jobs that match the name or wildcard + const jobsList: IJob[] = await GetJobs.getJobsByPrefix(session, jobName); + let fileCount = 0; + for(const job of jobsList ) + { + // Get spool files + const spoolFiles: IJobFile[] = await GetJobs.getSpoolFilesForJob(session, job); + + for (const spoolFile of spoolFiles) { + fileCount++; + let startingLine = 0; + let lineCount = 1; + + //If the max number of files have been search then end the search. + if(fileCount > fileLimit){ + Logger.getAppLogger().debug("searchJobs() - File limit reached"); + return replyBuffer; + } + + while(startingLine >= 0){ + const spoolContent = await this.searchSpoolContentCommon(session, searchString, searchRegex, + caseInsensitive, spoolFile, startingLine); + if(spoolContent.dataString.length > 0){ + if(startingLine == 0){ + if (spoolFile.procstep != null && spoolFile.procstep.length > 0) { + replyBuffer = replyBuffer + "Job Name: " + job.jobname + " Job Id: " + job.jobid + + " Spool file: " + spoolFile.ddname + "(ID #" + spoolFile.id + " Step: " + + spoolFile.stepname + " ProcStep: " + spoolFile.procstep +")" + "\n"; + + } else { + replyBuffer = replyBuffer + "Job Name: " + job.jobname + " Job Id: " + job.jobid + + " Spool file: " + spoolFile.ddname + "(ID #" + spoolFile.id + " Step: " + + spoolFile.stepname + ")" + "\n"; + } + } + const recordRange:string = spoolContent.response.headers['x-ibm-record-range']; + const lineNumberString:string = recordRange.substring(0, recordRange.indexOf(',')); + startingLine = Number(lineNumberString) + 1; + replyBuffer = replyBuffer + " Line " + startingLine + " : " + spoolContent.dataString; + + // If the search length is exceeded then end the search of this file. + lineCount++; + if(lineCount > searchLimit){ + Logger.getAppLogger().debug("searchJobs() - Search limit reached"); + startingLine = -1; + replyBuffer = replyBuffer + "\n"; + } + } + else{ + // If nothing more is found in this file, move on to the next one. + if(startingLine > 0){ + replyBuffer = replyBuffer + "\n"; + } + startingLine = -1; + } + } + } + } + + return replyBuffer; + } + + /** + * Search the spool of the specified file for the a search string or regular expression + * @static + * @param {AbstractSession} session - z/OSMF connection info + * @param {string} searchString - The string to search for in the spool output + * @param {string} searchRegex - The regex to search for in the spool output + * @param {boolean} caseInsensitive - Specify if a search is case sensitive + * @param {IJobFile} jobFile - The job spool file to search + * @param {number} startingLine - The line to start the searching from + * @returns {Promise} - promise that resolves to spool output and response headers + * @memberof searchJobs + */ + private static async searchSpoolContentCommon(session: AbstractSession, + searchString : string, + searchRegex:string, + caseInsensitive:boolean, + jobFile: IJobFile, + startingLine: number) { + Logger.getAppLogger().trace("SearchJobs.searchSpoolContentCommon()"); + const headers: any[] = [Headers.TEXT_PLAIN_UTF8]; + + let parameters: string = "/" + encodeURIComponent(jobFile.jobname) + "/" + encodeURIComponent(jobFile.jobid) + + JobsConstants.RESOURCE_SPOOL_FILES + "/" + encodeURIComponent(jobFile.id) + JobsConstants.RESOURCE_SPOOL_CONTENT; + + if(searchString != undefined) + parameters += "?search=" + searchString + "&maxreturnsize=1"; + else + parameters += "?research=" + searchRegex + "&maxreturnsize=1"; + + if(caseInsensitive === false) + parameters += "&insensitive=false"; + + if (startingLine > 0) { + headers.push({ [ZosmfHeaders.X_IBM_RECORD_RANGE]: startingLine+"-0"}); + } + + const requestOptions: IOptionsFullResponse = { + resource: JobsConstants.RESOURCE + parameters, + reqHeaders : headers + }; + const request: IRestClientResponse = await ZosmfRestClient.getExpectFullResponse(session, requestOptions); + + return request; + } +} diff --git a/packages/zosjobs/src/SubmitJobs.ts b/packages/zosjobs/src/SubmitJobs.ts index 41be52646b..7ce383d27c 100644 --- a/packages/zosjobs/src/SubmitJobs.ts +++ b/packages/zosjobs/src/SubmitJobs.ts @@ -505,7 +505,7 @@ export class SubmitJobs { } /** - * Getter for brightside logger + * Getter for Zowe logger * @returns {Logger} */ private static get log(): Logger { diff --git a/packages/zosjobs/src/doc/input/ISearchJobsParms.ts b/packages/zosjobs/src/doc/input/ISearchJobsParms.ts new file mode 100644 index 0000000000..2d8afb4dca --- /dev/null +++ b/packages/zosjobs/src/doc/input/ISearchJobsParms.ts @@ -0,0 +1,59 @@ +/* +* This program and the accompanying materials are made available under the terms of the +* Eclipse Public License v2.0 which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Copyright Contributors to the Zowe Project. +* +*/ + +/** + * Interface for search jobs z/OSMF API + * @export + * @interface ISearchJobsParms + */ +export interface ISearchJobsParms { + /** + * job name for the job you want to search + * @type {string} + * @memberof ISearchJobsParms + */ + jobName: string; + + /** + * The string to search for + * @type {string} + * @memberof ISearchJobsParms + */ + searchString?: string; + + /** + * The regular expression to search for + * @type {string} + * @memberof ISearchJobsParms + */ + searchRegex?: string; + + /** + * specify this option as `false` when wanting a case sensitive search + * @type {boolean} + * @memberof ISearchJobsParms + */ + caseInsensitive?: boolean; + + /** + * specify this option to limit the number of search hits per file + * @type {number} + * @memberof ISearchJobsParms + */ + searchLimit?: number; + + /** + * specify this option to limit the number of file searched + * @type {number} + * @memberof ISearchJobsParms + */ + fileLimit?: number; +} diff --git a/packages/zosjobs/src/index.ts b/packages/zosjobs/src/index.ts index c86d2dec12..a39c490d54 100644 --- a/packages/zosjobs/src/index.ts +++ b/packages/zosjobs/src/index.ts @@ -20,6 +20,7 @@ export * from "./doc/input/IDownloadAllSpoolContentParms"; export * from "./doc/input/IDownloadSpoolContentParms"; export * from "./doc/input/IGetJobsParms"; export * from "./doc/input/IMonitorJobWaitForParms"; +export * from "./doc/input/ISearchJobsParms"; export * from "./doc/input/ISubmitJclNotifyParms"; export * from "./doc/input/ISubmitJclParms"; export * from "./doc/input/ISubmitJobNotifyParms"; @@ -50,4 +51,5 @@ export * from "./GetJobs"; export * from "./JobsConstants"; export * from "./JobsMessages"; export * from "./MonitorJobs"; +export * from "./SearchJobs"; export * from "./SubmitJobs"; diff --git a/packages/zosjobs/typedoc.json b/packages/zosjobs/typedoc.json index 2b97359f2c..b15f87adc5 100644 --- a/packages/zosjobs/typedoc.json +++ b/packages/zosjobs/typedoc.json @@ -1,5 +1,6 @@ { "out": "./docs/typedoc/", - "exclude": "**/__tests__/**", + "exclude": ["**/__tests__/**"], + "entryPoints": ["src/index.ts"], "cleanOutputDir": true } \ No newline at end of file diff --git a/packages/zoslogs/CHANGELOG.md b/packages/zoslogs/CHANGELOG.md index 9b46e411ae..ae7de1e747 100644 --- a/packages/zoslogs/CHANGELOG.md +++ b/packages/zoslogs/CHANGELOG.md @@ -2,6 +2,27 @@ All notable changes to the Zowe z/OS logs SDK package will be documented in this file. +## Recent Changes + +- Update: Final prerelease + +## `8.0.0-next.202408131445` + +- Update: See `7.28.3` for details + +## `8.0.0-next.202403041352` + +- BugFix: Updated engine to Node 18.12.0. [#2074](https://github.com/zowe/zowe-cli/pull/2074) + +## `8.0.0-next.202402261705` + +- BugFix: Updated dependencies for technical currency. [#2061](https://github.com/zowe/zowe-cli/pull/2061) +- BugFix: Updated engine to Node 16.7.0. [#2061](https://github.com/zowe/zowe-cli/pull/2061) + +## `8.0.0-next.202311132045` + +- Major: First major version bump for V3 + ## `7.28.3` - BugFix: Refactored code to reduce the use of deprecated functions to prepare for upcoming Node.js 22 support. [#2191](https://github.com/zowe/zowe-cli/issues/2191) diff --git a/packages/zoslogs/package.json b/packages/zoslogs/package.json index 8d5aa440dd..d4ba523fdf 100644 --- a/packages/zoslogs/package.json +++ b/packages/zoslogs/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-logs-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "description": "Zowe SDK to interact with the z/OS logs", "author": "Zowe", "license": "EPL-2.0", @@ -45,12 +45,15 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" }, "peerDependencies": { - "@zowe/core-for-zowe-sdk": "^7.0.0", - "@zowe/imperative": "^5.0.0" + "@zowe/core-for-zowe-sdk": "^8.0.0-next", + "@zowe/imperative": "^8.0.0-next" + }, + "engines": { + "node": ">=18.12.0" } } diff --git a/packages/zoslogs/typedoc.json b/packages/zoslogs/typedoc.json index 2b97359f2c..b15f87adc5 100644 --- a/packages/zoslogs/typedoc.json +++ b/packages/zoslogs/typedoc.json @@ -1,5 +1,6 @@ { "out": "./docs/typedoc/", - "exclude": "**/__tests__/**", + "exclude": ["**/__tests__/**"], + "entryPoints": ["src/index.ts"], "cleanOutputDir": true } \ No newline at end of file diff --git a/packages/zosmf/CHANGELOG.md b/packages/zosmf/CHANGELOG.md index 9ac9cfa48c..6f9ae3ae2c 100644 --- a/packages/zosmf/CHANGELOG.md +++ b/packages/zosmf/CHANGELOG.md @@ -2,6 +2,40 @@ All notable changes to the Zowe z/OSMF SDK package will be documented in this file. +## Recent Changes + +- Update: Final prerelease + +## `8.0.0-next.202408131445` + +- Update: See `7.28.3` for details +- LTS Breaking: Removed the following obsolete V1 profile attributes from ZosmfBaseHandler: + - mZosmfProfile + - mZosmfLoadedProfile + +## `8.0.0-next.202403041352` + +- BugFix: Updated engine to Node 18.12.0. [#2074](https://github.com/zowe/zowe-cli/pull/2074) +- LTS Breaking: Removed the following obsolete V1 profile constants from ZosmfProfile.schema.properties + - createProfileExamples + - updateProfileExamples + +## `8.0.0-next.202402261705` + +- BugFix: Updated dependencies for technical currency. [#2061](https://github.com/zowe/zowe-cli/pull/2061) +- BugFix: Updated engine to Node 16.7.0. [#2061](https://github.com/zowe/zowe-cli/pull/2061) + +## `8.0.0-next.202402021649` + +- LTS Breaking: Removed the following constants from ZosmfSession + - ZOSMF_OPTION_HOST_PROFILE use ZOSMF_OPTION_HOST instead + - ZOSMF_OPTION_USER_PROFILE use ZOSMF_OPTION_USER instead + - ZOSMF_OPTION_PASSWORD_PROFILE use ZOSMF_OPTION_PASSWORD instead + +## `8.0.0-next.202311132045` + +- Major: First major version bump for V3 + ## `7.28.3` - BugFix: Refactored code to reduce the use of deprecated functions to prepare for upcoming Node.js 22 support. [#2191](https://github.com/zowe/zowe-cli/issues/2191) diff --git a/packages/zosmf/__tests__/__system__/methods/CheckStatus.system.test.ts b/packages/zosmf/__tests__/__system__/methods/CheckStatus.system.test.ts index b71b712552..0c99be92ea 100644 --- a/packages/zosmf/__tests__/__system__/methods/CheckStatus.system.test.ts +++ b/packages/zosmf/__tests__/__system__/methods/CheckStatus.system.test.ts @@ -92,7 +92,10 @@ describe("Check Status Api", () => { expect(error).toBeTruthy(); expect(response).toBeFalsy(); - expect(error.message).toMatch(/(Error: getaddrinfo).*(badHost)/); + const jsonCauseErrors = error.causeErrors; + expect(jsonCauseErrors.code).toEqual("ENOTFOUND"); + expect(jsonCauseErrors.syscall).toEqual("getaddrinfo"); + expect(jsonCauseErrors.hostname).toEqual(badHostName); }); it("should return with proper message for invalid port", async () => { @@ -118,8 +121,10 @@ describe("Check Status Api", () => { expect(error).toBeTruthy(); expect(response).toBeFalsy(); - expect(error.message).toContain(`Error: connect ECONNREFUSED`); - expect(error.message).toContain(badPort.toString()); + const jsonCauseErrors = error.causeErrors; + expect(jsonCauseErrors.code).toMatch(/(ECONNREFUSED|ECONNRESET)/); + expect(jsonCauseErrors.syscall).toEqual("connect"); + expect(jsonCauseErrors.port).toEqual(badPort); }); }); }); diff --git a/packages/zosmf/__tests__/__system__/methods/ListDefinedSystems.system.test.ts b/packages/zosmf/__tests__/__system__/methods/ListDefinedSystems.system.test.ts index dde42a55f4..84ed601948 100644 --- a/packages/zosmf/__tests__/__system__/methods/ListDefinedSystems.system.test.ts +++ b/packages/zosmf/__tests__/__system__/methods/ListDefinedSystems.system.test.ts @@ -92,7 +92,10 @@ describe("List Defined Systems Api", () => { expect(error).toBeTruthy(); expect(response).toBeFalsy(); - expect(error.message).toMatch(/(Error: getaddrinfo).*(badHost)/); + const jsonCauseErrors = error.causeErrors; + expect(jsonCauseErrors.code).toEqual("ENOTFOUND"); + expect(jsonCauseErrors.syscall).toEqual("getaddrinfo"); + expect(jsonCauseErrors.hostname).toEqual(badHostName); }); it("should return with proper message for invalid port", async () => { @@ -118,7 +121,9 @@ describe("List Defined Systems Api", () => { expect(error).toBeTruthy(); expect(response).toBeFalsy(); - expect(error.message).toMatch(/Error: (connect|read) (ECONNREFUSED|ECONNRESET)/); + const jsonCauseErrors = error.causeErrors; + expect(jsonCauseErrors.code).toMatch(/(ECONNREFUSED|ECONNRESET)/); + expect(jsonCauseErrors.syscall).toMatch(/(connect|read)/); }); }); }); diff --git a/packages/zosmf/package.json b/packages/zosmf/package.json index ea7f082e28..fbfdfc80d5 100644 --- a/packages/zosmf/package.json +++ b/packages/zosmf/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zosmf-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "description": "Zowe SDK to interact with the z/OS Management Facility", "author": "Zowe", "license": "EPL-2.0", @@ -44,12 +44,15 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "devDependencies": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" }, "peerDependencies": { - "@zowe/core-for-zowe-sdk": "^7.0.0", - "@zowe/imperative": "^5.0.0" + "@zowe/core-for-zowe-sdk": "^8.0.0-next", + "@zowe/imperative": "^8.0.0-next" + }, + "engines": { + "node": ">=18.12.0" } } diff --git a/packages/zosmf/src/ZosmfBaseHandler.ts b/packages/zosmf/src/ZosmfBaseHandler.ts index 2d41100378..67d3c56d5a 100644 --- a/packages/zosmf/src/ZosmfBaseHandler.ts +++ b/packages/zosmf/src/ZosmfBaseHandler.ts @@ -14,14 +14,12 @@ import { ICommandArguments, ICommandHandler, IHandlerParameters, - IProfile, IHandlerResponseConsoleApi, IHandlerFormatOutputApi, IHandlerResponseDataApi, IHandlerProgressApi, IImperativeError, ImperativeError, - IProfileLoaded, ISession, Session, ConnectionPropsForSessCfg @@ -38,18 +36,6 @@ export abstract class ZosmfBaseHandler implements ICommandHandler { */ protected mSession: AbstractSession; - /** - * Loaded z/OSMF profile if needed - * @deprecated - */ - protected mZosmfProfile: IProfile; - - /** - * Loaded z/OSMF profile with meta information - * @deprecated - */ - protected mZosmfLoadedProfile: IProfileLoaded; - /** * Command line arguments passed */ @@ -71,12 +57,6 @@ export abstract class ZosmfBaseHandler implements ICommandHandler { public async process(commandParameters: IHandlerParameters) { this.mHandlerParams = commandParameters; - // Nothing uses this, but extenders might... -awharn - // eslint-disable-next-line deprecation/deprecation - this.mZosmfProfile = commandParameters.profiles.get("zosmf", false); - // This one too... -awharn - // eslint-disable-next-line deprecation/deprecation - this.mZosmfLoadedProfile = commandParameters.profiles.getMeta("zosmf", false); const sessCfg: ISession = ZosmfSession.createSessCfgFromArgs( commandParameters.arguments diff --git a/packages/zosmf/src/ZosmfSession.ts b/packages/zosmf/src/ZosmfSession.ts index e072c77989..0e6cc72bca 100644 --- a/packages/zosmf/src/ZosmfSession.ts +++ b/packages/zosmf/src/ZosmfSession.ts @@ -17,7 +17,7 @@ import { } from "@zowe/imperative"; /** - * Utility Methods for Brightside + * Utility Methods for Zowe * @export */ export class ZosmfSession { @@ -36,12 +36,6 @@ export class ZosmfSession { group: ZosmfSession.ZOSMF_CONNECTION_OPTION_GROUP }; - /** - * Option used in profile creation and commands for hostname for z/OSMF - * @deprecated Use ZOSMF_OPTION_HOST instead - */ - public static ZOSMF_OPTION_HOST_PROFILE = ZosmfSession.ZOSMF_OPTION_HOST; - /** * Option used in profile creation and commands for port for z/OSMF */ @@ -66,12 +60,6 @@ export class ZosmfSession { group: ZosmfSession.ZOSMF_CONNECTION_OPTION_GROUP }; - /** - * Option used in profile creation and commands for username / ID for z/OSMF - * @deprecated Use ZOSMF_OPTION_USER instead - */ - public static ZOSMF_OPTION_USER_PROFILE = ZosmfSession.ZOSMF_OPTION_USER; - /** * Option used in profile creation and commands for password/passphrase for z/OSMF */ @@ -84,12 +72,6 @@ export class ZosmfSession { group: ZosmfSession.ZOSMF_CONNECTION_OPTION_GROUP }; - /** - * Option used in profile creation and commands for password/passphrase for z/OSMF - * @deprecated Use ZOSMF_OPTION_PASSWORD instead - */ - public static ZOSMF_OPTION_PASSWORD_PROFILE = ZosmfSession.ZOSMF_OPTION_PASSWORD; - /** * Option used in profile creation and commands for rejectUnauthorized setting for connecting to z/OSMF */ diff --git a/packages/zosmf/src/constants/Zosmf.profile.ts b/packages/zosmf/src/constants/Zosmf.profile.ts index 4d7fc0a941..822cf94a6c 100644 --- a/packages/zosmf/src/constants/Zosmf.profile.ts +++ b/packages/zosmf/src/constants/Zosmf.profile.ts @@ -86,40 +86,5 @@ export const ZosmfProfile: ICommandProfileTypeConfiguration = } }, required: [] - }, - createProfileExamples: [ - { - options: "zos123 --host zos123 --port 1443 --user ibmuser --password myp4ss", - description: "Create a zosmf profile called 'zos123' to connect to z/OSMF at host zos123 and port 1443" - }, - { - options: "zos124 --host zos124 --user ibmuser --password myp4ss --reject-unauthorized false", - description: "Create a zosmf profile called 'zos124' to connect to z/OSMF at the host zos124 (default port - 443) " + - "and allow self-signed certificates" - }, - { - options: "zos125 --host zos125 --port 1443", - description: "Create a zosmf profile called 'zos125' to connect to z/OSMF at the host zos125 and port 1443, " + - " not specifying a username or password so they are not stored on disk; these will need to be specified on every command" - }, - { - options: "zos126 --reject-unauthorized false", - description: "Create a zosmf profile called 'zos126' to connect to z/OSMF on the default port 443 and allow self-signed " + - "certificates, not specifying a username, password, or host so they are not stored on disk; these will need to be " + - "specified on every command" - }, - { - options: "zosAPIML --host zosAPIML --port 7554 --user ibmuser --password myp4ss --reject-unauthorized false --base-path ibmzosmf/api/v1", - description: "Create a zosmf profile called 'zosAPIML' to connect to z/OSMF via the Zowe API Mediation Layer running at host " + - "'zosAPIML', port '7554', and allow for self-signed certificates. To reduce duplication, you could elect to store the 'host', " + - "'port', 'reject-unauthorized', 'user', and 'password' values for the API Mediation Layer in a base profile and only store " + - "the 'base-path' of the service in the zosmf profile" - } - ], - updateProfileExamples: [ - { - options: "zos123 --user newuser --password newp4ss", - description: "Update a zosmf profile named 'zos123' with a new username and password" - } - ] + } }; diff --git a/packages/zosmf/typedoc.json b/packages/zosmf/typedoc.json index 2b97359f2c..b15f87adc5 100644 --- a/packages/zosmf/typedoc.json +++ b/packages/zosmf/typedoc.json @@ -1,5 +1,6 @@ { "out": "./docs/typedoc/", - "exclude": "**/__tests__/**", + "exclude": ["**/__tests__/**"], + "entryPoints": ["src/index.ts"], "cleanOutputDir": true } \ No newline at end of file diff --git a/packages/zostso/CHANGELOG.md b/packages/zostso/CHANGELOG.md index a36471796b..3322729f09 100644 --- a/packages/zostso/CHANGELOG.md +++ b/packages/zostso/CHANGELOG.md @@ -2,6 +2,34 @@ All notable changes to the Zowe z/OS TSO SDK package will be documented in this file. +## Recent Changes + +- Update: Final prerelease + +## `8.0.0-next.202408131445` + +- Update: See `7.28.3` for details + +## `8.0.0-next.202403041352` + +- BugFix: Updated engine to Node 18.12.0. [#2074](https://github.com/zowe/zowe-cli/pull/2074) +- LTS Breaking: Removed the following obsolete V1 profile constants from ZosTsoProfile.schema.properties + - createProfileExamples + - updateProfileExamples + +## `8.0.0-next.202402261705` + +- BugFix: Updated dependencies for technical currency. [#2061](https://github.com/zowe/zowe-cli/pull/2061) +- BugFix: Updated engine to Node 16.7.0. [#2061](https://github.com/zowe/zowe-cli/pull/2061) + +## `8.0.0-next.202402021649` + +- LTS Breaking: Moved all constants from `zowe-cli/packages/cli/src/zostso/constants/ZosTso.constants.ts` to `@zowe/zos-tso-for-zowe-sdk` + +## `8.0.0-next.202311132045` + +- Major: First major version bump for V3 + ## `7.28.3` - BugFix: Refactored code to reduce the use of deprecated functions to prepare for upcoming Node.js 22 support. [#2191](https://github.com/zowe/zowe-cli/issues/2191) diff --git a/packages/zostso/package.json b/packages/zostso/package.json index eeb7b8ea15..f079469c6b 100644 --- a/packages/zostso/package.json +++ b/packages/zostso/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-tso-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "description": "Zowe SDK to interact with TSO on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -45,15 +45,18 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "@zowe/zosmf-for-zowe-sdk": "7.29.2" + "@zowe/zosmf-for-zowe-sdk": "8.0.0-next.202409111528" }, "devDependencies": { - "@zowe/cli-test-utils": "7.29.2", - "@zowe/core-for-zowe-sdk": "7.29.2", - "@zowe/imperative": "5.27.1" + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/core-for-zowe-sdk": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" }, "peerDependencies": { - "@zowe/core-for-zowe-sdk": "^7.0.0", - "@zowe/imperative": "^5.0.0" + "@zowe/core-for-zowe-sdk": "^8.0.0-next", + "@zowe/imperative": "^8.0.0-next" + }, + "engines": { + "node": ">=18.12.0" } } diff --git a/packages/zostso/src/SendTso.ts b/packages/zostso/src/SendTso.ts index a0b37ce4f0..290a23b6bd 100644 --- a/packages/zostso/src/SendTso.ts +++ b/packages/zostso/src/SendTso.ts @@ -90,7 +90,7 @@ export class SendTso { if (!(tso.tsoData == null)) { tso.tsoData.forEach((data) => { if (data[TsoConstants.TSO_MESSAGE]) { - messages += (data[TsoConstants.TSO_MESSAGE].DATA + "\n"); + messages += data[TsoConstants.TSO_MESSAGE].DATA + "\n"; } else if (data[TsoConstants.TSO_PROMPT]) { // handle case where we get a PROMPT but no data has been accumulated yet if (messages !== "") { diff --git a/packages/zostso/src/constants/ZosTso.profile.ts b/packages/zostso/src/constants/ZosTso.profile.ts index 67ed8955e0..21b407ce98 100644 --- a/packages/zostso/src/constants/ZosTso.profile.ts +++ b/packages/zostso/src/constants/ZosTso.profile.ts @@ -57,27 +57,5 @@ export const ZosTsoProfile: ICommandProfileTypeConfiguration = { } }, required: [] - }, - createProfileExamples: [ - { - description: "Create a tso profile called 'myprof' with default settings and JES accounting information of 'IZUACCT'", - options: "myprof -a IZUACCT" - }, - { - description: "Create a tso profile called 'largeregion' with a region size of 8192, a logon procedure of MYPROC, and " + - "JES accounting information of '1234'", - options: "largeregion -a 1234 --rs 8192" - }, - { - description: "Create a tso profile called 'myprof2' with default settings and region size of 8192, without storing the user " + - "account on disk", - options: "myprof2 --rs 8192" - } - ], - updateProfileExamples: [ - { - description: "Update a tso profile called myprof with new JES accounting information", - options: "myprof -a NEWACCT" - } - ] + } }; diff --git a/packages/zostso/typedoc.json b/packages/zostso/typedoc.json index 2b97359f2c..b15f87adc5 100644 --- a/packages/zostso/typedoc.json +++ b/packages/zostso/typedoc.json @@ -1,5 +1,6 @@ { "out": "./docs/typedoc/", - "exclude": "**/__tests__/**", + "exclude": ["**/__tests__/**"], + "entryPoints": ["src/index.ts"], "cleanOutputDir": true } \ No newline at end of file diff --git a/packages/zosuss/CHANGELOG.md b/packages/zosuss/CHANGELOG.md index 34d5403fb1..274b13b1ad 100644 --- a/packages/zosuss/CHANGELOG.md +++ b/packages/zosuss/CHANGELOG.md @@ -2,11 +2,55 @@ All notable changes to the Zowe z/OS USS SDK package will be documented in this file. -## `7.29.0` +## Recent Changes + +- Update: Final prerelease + +## `8.0.0-next.202408131445` + +- Update: See `7.28.3` for details + +## `8.0.0-next.202408092029` - BugFix: Resolved bug that resulted in user not being prompted for a key passphrase if it is located in the secure credential array of the ssh profile. [#1770](https://github.com/zowe/zowe-cli/issues/1770) - Enhancement: `SshBaseHandler` command processor will now prompt user up to 3 times to enter the correct keyPassphrase in the case that the stored value is incorrect or no value is stored. [#1770](https://github.com/zowe/zowe-cli/issues/1770) +## `8.0.0-next.202403132009` + +- Enhancement: Provide more legible errors to user when they are missing user/password credentials while +running `zowe zos-uss issue ssh` commands. [#2081](https://github.com/zowe/zowe-cli/pull/2081) + +## `8.0.0-next.202403041352` + +- BugFix: Updated engine to Node 18.12.0. [#2074](https://github.com/zowe/zowe-cli/pull/2074) +- LTS Breaking: Removed the following obsolete V1 profile constant from ZosUssProfile.schema.properties + - createProfileExamples + +## `8.0.0-next.202402261705` + +- BugFix: Updated additional dependencies for technical currency. [#2061](https://github.com/zowe/zowe-cli/pull/2061) +- BugFix: Updated engine to Node 16.7.0. [#2061](https://github.com/zowe/zowe-cli/pull/2061) + +## `8.0.0-next.202402211923` + +- BugFix: Updated dependencies for technical currency [#2057](https://github.com/zowe/zowe-cli/pull/2057) + +## `8.0.0-next.202402021649` + +- LTS Breaking: Removed the following previously deprecated items: + - Removed the following constants from SshSession.ts + - SSH_OPTION_USER_PROFILE use SSH_OPTION_USER + - SSH_OPTION_HOST_PROFILE use SSH_OPTION_HOST + - Removed statCmdFlag as an export from Shell.ts + +## `8.0.0-next.202311282012` + +- LTS Breaking: Unpinned dependency versions to allow for patch/minor version updates for dependencies [#1968](https://github.com/zowe/zowe-cli/issues/1968) + +## `8.0.0-next.202311132045` + +- Major: First major version bump for V3 + ## `7.28.3` - BugFix: Refactored code to reduce the use of deprecated functions to prepare for upcoming Node.js 22 support. [#2191](https://github.com/zowe/zowe-cli/issues/2191) diff --git a/packages/zosuss/__tests__/__unit__/Shell.unit.test.ts b/packages/zosuss/__tests__/__unit__/Shell.unit.test.ts index e41b5cec9b..f8c3b397a7 100644 --- a/packages/zosuss/__tests__/__unit__/Shell.unit.test.ts +++ b/packages/zosuss/__tests__/__unit__/Shell.unit.test.ts @@ -61,8 +61,8 @@ const mockShell = jest.fn().mockImplementation((callback) => { const stdoutHandler = jest.fn(); function checkMockFunctionsWithCommand(command: string) { - expect(mockConnect).toBeCalled(); - expect(mockShell).toBeCalled(); + expect(mockConnect).toHaveBeenCalled(); + expect(mockShell).toHaveBeenCalled(); // Check the stream.end() function is called with an argument containing the SSH command expect(mockStreamWrite.mock.calls[0][0]).toMatch(command); @@ -118,9 +118,9 @@ describe("Shell", () => { caughtError = error; } - expect(mockConnect).toBeCalled(); - expect(mockShell).toBeCalled(); - expect(mockStreamEnd).toBeCalled(); + expect(mockConnect).toHaveBeenCalled(); + expect(mockShell).toHaveBeenCalled(); + expect(mockStreamEnd).toHaveBeenCalled(); expect(caughtError.message).toBe(ZosUssMessages.expiredPassword.message); }); @@ -138,9 +138,9 @@ describe("Shell", () => { caughtError = error; } - expect(mockConnect).toBeCalled(); - expect(mockShell).toBeCalled(); - expect(mockStreamEnd).toBeCalled(); + expect(mockConnect).toHaveBeenCalled(); + expect(mockShell).toHaveBeenCalled(); + expect(mockStreamEnd).toHaveBeenCalled(); expect(caughtError.message).toBe(ZosUssMessages.allAuthMethodsFailed.message); }); @@ -158,9 +158,9 @@ describe("Shell", () => { caughtError = error; } - expect(mockConnect).toBeCalled(); - expect(mockShell).toBeCalled(); - expect(mockStreamEnd).toBeCalled(); + expect(mockConnect).toHaveBeenCalled(); + expect(mockShell).toHaveBeenCalled(); + expect(mockStreamEnd).toHaveBeenCalled(); expect(caughtError.message).toBe(ZosUssMessages.handshakeTimeout.message); }); @@ -178,9 +178,9 @@ describe("Shell", () => { caughtError = error; } - expect(mockConnect).toBeCalled(); - expect(mockShell).toBeCalled(); - expect(mockStreamEnd).toBeCalled(); + expect(mockConnect).toHaveBeenCalled(); + expect(mockShell).toHaveBeenCalled(); + expect(mockStreamEnd).toHaveBeenCalled(); expect(caughtError.message).toContain(ZosUssMessages.connectionRefused.message); }); @@ -198,9 +198,9 @@ describe("Shell", () => { caughtError = error; } - expect(mockConnect).toBeCalled(); - expect(mockShell).toBeCalled(); - expect(mockStreamEnd).toBeCalled(); + expect(mockConnect).toHaveBeenCalled(); + expect(mockShell).toHaveBeenCalled(); + expect(mockStreamEnd).toHaveBeenCalled(); expect(caughtError.message).toContain(ZosUssMessages.unexpected.message); }); }); diff --git a/packages/zosuss/__tests__/__unit__/SshBaseHandler.unit.test.ts b/packages/zosuss/__tests__/__unit__/SshBaseHandler.unit.test.ts index 5e9365250a..3f8ee619f4 100644 --- a/packages/zosuss/__tests__/__unit__/SshBaseHandler.unit.test.ts +++ b/packages/zosuss/__tests__/__unit__/SshBaseHandler.unit.test.ts @@ -9,7 +9,7 @@ * */ -import { IHandlerParameters, IProfile, CommandProfiles, ConnectionPropsForSessCfg } from "@zowe/imperative"; +import { IHandlerParameters, ConnectionPropsForSessCfg } from "@zowe/imperative"; import { mockHandlerParameters } from "@zowe/cli-test-utils"; import { join, normalize } from "path"; import { Shell } from "../../src/Shell"; @@ -45,73 +45,28 @@ const UNIT_TEST_SSH_PROF_OPTS_PRIVATE_KEY_WITH_PASSPHRASE_NO_USER = { keyPassPhrase: "dummyPassPhrase123" }; - -// A mocked profile map with ssh profile -const UNIT_TEST_PROFILE_MAP = new Map(); -UNIT_TEST_PROFILE_MAP.set( - "ssh", [{ - name: "ssh", - type: "ssh", - ...UNIT_TEST_SSH_PROF_OPTS - }] -); -const UNIT_TEST_PROFILES_SSH = new CommandProfiles(UNIT_TEST_PROFILE_MAP); - -const UNIT_TEST_PROFILE_MAP_PRIVATE_KEY = new Map(); -UNIT_TEST_PROFILE_MAP_PRIVATE_KEY.set( - "ssh", [{ - name: "ssh", - type: "ssh", - ...UNIT_TEST_SSH_PROF_OPTS_PRIVATE_KEY - }] -); -const UNIT_TEST_PROFILE_MAP_PRIVATE_KEY_WITH_PASSPHRASE = new Map(); -UNIT_TEST_PROFILE_MAP_PRIVATE_KEY_WITH_PASSPHRASE.set( - "ssh", [{ - name: "ssh", - type: "ssh", - ...UNIT_TEST_SSH_PROF_OPTS_PRIVATE_KEY_WITH_PASSPHRASE - }] -); -const UNIT_TEST_PROFILE_MAP_PRIVATE_KEY_WITH_PASSPHRASE_NO_USER = new Map(); -UNIT_TEST_PROFILE_MAP_PRIVATE_KEY_WITH_PASSPHRASE.set( - "ssh", [{ - name: "ssh", - type: "ssh", - ...UNIT_TEST_SSH_PROF_OPTS_PRIVATE_KEY_WITH_PASSPHRASE_NO_USER - }] -); - -const UNIT_TEST_PROFILES_SSH_PRIVATE_KEY = new CommandProfiles(UNIT_TEST_PROFILE_MAP_PRIVATE_KEY); -const UNIT_TEST_PROFILES_SSH_PRIVATE_KEY_WITH_PASSPHRASE = new CommandProfiles(UNIT_TEST_PROFILE_MAP_PRIVATE_KEY_WITH_PASSPHRASE); -const UNIT_TEST_PROFILES_SSH_PRIVATE_KEY_WITH_PASSPHRASE_NO_USER = new CommandProfiles(UNIT_TEST_PROFILE_MAP_PRIVATE_KEY_WITH_PASSPHRASE_NO_USER); - // Mocked parameters for the unit tests const DEFAULT_PARAMETERS: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_SSH_PROF_OPTS, positionals: ["zos-uss", "issue", "ssh"], - definition: {} as any, - profiles: UNIT_TEST_PROFILES_SSH + definition: {} as any }); const DEFAULT_PARAMETERS_PRIVATE_KEY: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_SSH_PROF_OPTS_PRIVATE_KEY, positionals: ["zos-uss", "issue", "ssh"], - definition: {} as any, - profiles: UNIT_TEST_PROFILES_SSH_PRIVATE_KEY + definition: {} as any }); const DEFAULT_PARAMETERS_KEY_PASSPHRASE: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_SSH_PROF_OPTS_PRIVATE_KEY_WITH_PASSPHRASE, positionals: ["zos-uss", "issue", "ssh"], - definition: {} as any, - profiles: UNIT_TEST_PROFILES_SSH_PRIVATE_KEY_WITH_PASSPHRASE, + definition: {} as any }); const DEFAULT_PARAMETERS_KEY_PASSPHRASE_NO_USER: IHandlerParameters = mockHandlerParameters({ arguments: UNIT_TEST_SSH_PROF_OPTS_PRIVATE_KEY_WITH_PASSPHRASE_NO_USER, positionals: ["zos-uss", "issue", "ssh"], - definition: {} as any, - profiles: UNIT_TEST_PROFILES_SSH_PRIVATE_KEY_WITH_PASSPHRASE_NO_USER, + definition: {} as any }); class myHandler extends SshBaseHandler { diff --git a/packages/zosuss/package.json b/packages/zosuss/package.json index d4529fe2d5..2260158b4b 100644 --- a/packages/zosuss/package.json +++ b/packages/zosuss/package.json @@ -1,6 +1,6 @@ { "name": "@zowe/zos-uss-for-zowe-sdk", - "version": "7.29.2", + "version": "8.0.0-next.202409111528", "description": "Zowe SDK to interact with USS on z/OS", "author": "Zowe", "license": "EPL-2.0", @@ -45,14 +45,17 @@ "prepack": "node ../../scripts/prepareLicenses.js" }, "dependencies": { - "ssh2": "1.15.0" + "ssh2": "^1.15.0" }, "devDependencies": { - "@types/ssh2": "^1.11.0", - "@zowe/cli-test-utils": "7.29.2", - "@zowe/imperative": "5.27.1" + "@types/ssh2": "^1.11.19", + "@zowe/cli-test-utils": "8.0.0-next.202409111528", + "@zowe/imperative": "8.0.0-next.202409111528" }, "peerDependencies": { - "@zowe/imperative": "^5.2.0" + "@zowe/imperative": "^8.0.0-next" + }, + "engines": { + "node": ">=18.12.0" } } diff --git a/packages/zosuss/src/Shell.ts b/packages/zosuss/src/Shell.ts index e303e22820..dc7ff271f5 100644 --- a/packages/zosuss/src/Shell.ts +++ b/packages/zosuss/src/Shell.ts @@ -145,11 +145,11 @@ export class Shell { port: session.ISshSession.port, username: session.ISshSession.user, password: session.ISshSession.password, - privateKey: (session.ISshSession.privateKey != null && session.ISshSession.privateKey !== "undefined") ? + privateKey: session.ISshSession.privateKey != null && session.ISshSession.privateKey !== "undefined" ? require("fs").readFileSync(session.ISshSession.privateKey) : "", passphrase: session.ISshSession.keyPassphrase, authHandler: this.authenticationHandler(authsAllowed), - readyTimeout: (session.ISshSession.handshakeTimeout != null && session.ISshSession.handshakeTimeout !== undefined) ? + readyTimeout: session.ISshSession.handshakeTimeout != null && session.ISshSession.handshakeTimeout !== undefined ? session.ISshSession.handshakeTimeout : 0 } as any); }); @@ -174,8 +174,3 @@ export class Shell { }; } } - -/** - * @deprecated Use `Shell.startCmdFlag` instead. - */ -export const startCmdFlag = Shell.startCmdFlag; diff --git a/packages/zosuss/src/SshBaseHandler.ts b/packages/zosuss/src/SshBaseHandler.ts index 81e4f388f1..d3927573e4 100644 --- a/packages/zosuss/src/SshBaseHandler.ts +++ b/packages/zosuss/src/SshBaseHandler.ts @@ -23,7 +23,6 @@ import { ImperativeError, ConnectionPropsForSessCfg, SessConstants, - IProfile } from "@zowe/imperative"; import { SshSession } from "./SshSession"; import { ISshSession } from "./doc/ISshSession"; @@ -39,12 +38,6 @@ export abstract class SshBaseHandler implements ICommandHandler { */ protected mSession: SshSession; - /** - * Loaded z/OS SSH profile if needed - * @deprecated - */ - protected mSshProfile: IProfile; - /** * Command line arguments passed */ @@ -65,9 +58,6 @@ export abstract class SshBaseHandler implements ICommandHandler { */ public async process(commandParameters: IHandlerParameters) { this.mHandlerParams = commandParameters; - // Why is this here? NOTHING uses it, but I suppose an extender MIGHT be... -awharn - // eslint-disable-next-line deprecation/deprecation - this.mSshProfile = commandParameters.profiles.get("ssh", false); const sshSessCfgOverride: IOverridePromptConnProps[] = [ { diff --git a/packages/zosuss/src/SshSession.ts b/packages/zosuss/src/SshSession.ts index 7393d1de97..f28c174151 100644 --- a/packages/zosuss/src/SshSession.ts +++ b/packages/zosuss/src/SshSession.ts @@ -18,7 +18,7 @@ import { ISshSession } from "./doc/ISshSession"; /** - * Utility Methods for Brightside + * Utility Methods for Zowe * @export */ export class SshSession { @@ -54,11 +54,6 @@ export class SshSession { group: SshSession.SSH_CONNECTION_OPTION_GROUP }; - /** - * @deprecated Use SSH_OPTION_HOST - */ - public static SSH_OPTION_HOST_PROFILE: ICommandOptionDefinition = SshSession.SSH_OPTION_HOST; - /** * Option used in profile creation and commands for port for z/OS SSH */ @@ -83,11 +78,6 @@ export class SshSession { group: SshSession.SSH_CONNECTION_OPTION_GROUP }; - /** - * @deprecated Use SSH_OPTION_USER - */ - public static SSH_OPTION_USER_PROFILE: ICommandOptionDefinition = SshSession.SSH_OPTION_USER; - /** * Option used in profile creation and commands for password/passphrase for z/OS SSH */ diff --git a/packages/zosuss/src/constants/ZosUss.profile.ts b/packages/zosuss/src/constants/ZosUss.profile.ts index 472526ec6c..6014778571 100644 --- a/packages/zosuss/src/constants/ZosUss.profile.ts +++ b/packages/zosuss/src/constants/ZosUss.profile.ts @@ -58,26 +58,5 @@ export const ZosUssProfile: ICommandProfileTypeConfiguration = { } }, required: [] - }, - createProfileExamples: [ - { - options: "ssh111 --host sshhost --user ibmuser --password myp4ss", - description: "Create a ssh profile called 'ssh111' to connect to z/OS SSH server at host 'zos123' and default port 22" - }, - { - options: "ssh222 --host sshhost --port 13022 --user ibmuser --password myp4ss", - description: "Create a ssh profile called 'ssh222' to connect to z/OS SSH server at host 'zos123' and port 13022" - }, - { - options: "ssh333 --host sshhost --user ibmuser --privateKey /path/to/privatekey --keyPassphrase privateKeyPassphrase", - description: "Create a ssh profile called 'ssh333' to connect to z/OS SSH server at host 'zos123' " + - "using a privatekey '/path/to/privatekey' and its decryption passphrase 'privateKeyPassphrase' " + - "for privatekey authentication" - }, - { - options: "ssh444 --privateKey /path/to/privatekey", - description: "Create a ssh profile called 'ssh444' to connect to z/OS SSH server on default port 22, without specifying " + - "username, host, or password, preventing those values from being stored on disk" - } - ] + } }; diff --git a/packages/zosuss/typedoc.json b/packages/zosuss/typedoc.json index 2b97359f2c..b15f87adc5 100644 --- a/packages/zosuss/typedoc.json +++ b/packages/zosuss/typedoc.json @@ -1,5 +1,6 @@ { "out": "./docs/typedoc/", - "exclude": "**/__tests__/**", + "exclude": ["**/__tests__/**"], + "entryPoints": ["src/index.ts"], "cleanOutputDir": true } \ No newline at end of file diff --git a/release.config.js b/release.config.js index 5fe2162016..b59da5d4f5 100644 --- a/release.config.js +++ b/release.config.js @@ -1,18 +1,19 @@ module.exports = { branches: [ - { - name: "master", - level: "minor" - }, + // Temporarily put zowe-v2-lts branch first in the list. + // It should move down once latest becomes zowe-v3-lts. { name: "zowe-v?-lts", level: "patch" + }, + // Temporarily publish master branch as @next prerelease. + // When V3 goes live, remember to update alias tags below. + { + name: "master", + level: "none", + prerelease: true, + channel: "next" } - // { - // name: "next", - // prerelease: true, - // dependencies: { "@zowe/perf-timing": "latest" } - // } ], plugins: [ ["@octorelease/changelog", { @@ -35,11 +36,11 @@ module.exports = { }], ["@octorelease/lerna", { aliasTags: { - "latest": ["zowe-v2-lts"] + "latest": ["zowe-v2-lts"], + "next": ["zowe-v3-lts"] }, pruneShrinkwrap: ["@zowe/cli"], - smokeTest: true, - versionIndependent: ["@zowe/imperative"] + smokeTest: true }], ["@octorelease/github", { checkPrLabels: true, diff --git a/scripts/performanceAnalysis.js b/scripts/performanceAnalysis.js deleted file mode 100644 index 875a7b1e82..0000000000 --- a/scripts/performanceAnalysis.js +++ /dev/null @@ -1,85 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -/** - * Read in a directory containing json files of runs of scripts/performanceTest.js - * from different systems, and analyze the results, providing a summary - */ - -const fs = require("fs"); -const {TextUtils} = require("@brightside/imperative"); -const {resolve} = require("path"); -const jsonFilesDirectory = resolve(process.argv[2]); -if (jsonFilesDirectory == null) { - console.error("You must specify a directory containing performance test JSON files as the " + - "first positional argument to this script."); - process.exit(1); -} - -console.log("Analyzing performance test results in the directory '%s'", jsonFilesDirectory); -const filesInDir = fs.readdirSync(jsonFilesDirectory); -const jsonFiles = []; -for (const file of filesInDir) { - if (file.indexOf(".json") >= 0) { - jsonFiles.push(file); - } -} - -const finalResults = {}; - -for (const file of jsonFiles) { - const jsonResult = require(resolve(jsonFilesDirectory + "/" + file)); - for (const result of jsonResult.results) { - if (finalResults[result.label] == null) { - // if this is the first time we've seen this label, initialize the result for the task - finalResults[result.label] = { - longest: -1, - shortest: 99999999999999999999999999999, - numResults: 0, - total: 0, - average: 0 - }; - } - - finalResults[result.label].total += result.elapsedTime; - finalResults[result.label].numResults++; - if (finalResults[result.label].longest < result.elapsedTime) { - finalResults[result.label].longest = result.elapsedTime; - } - if (finalResults[result.label].shortest > result.elapsedTime) { - finalResults[result.label].shortest = result.elapsedTime; - } - } -} - -for (const label of Object.keys(finalResults)) { - finalResults[label].average = (finalResults[label].total / finalResults[label].numResults).toFixed(2); -} - -/** - * Get a report of the results - * - * First, add human-readable keys to the result object - */ -const stringifiedResults = Object.keys(finalResults).map(function (label) { - const result = finalResults[label]; - const newResult = {}; - newResult.Task = label; - newResult["Shortest time (ms)"] = result.shortest; - newResult["Average time (ms)"] = result.average; - newResult["Longest time (ms)"] = result.longest; - newResult["Number of tests"] = result.numResults; - delete newResult.elapsedTime; - return newResult; -}); - -const resultTable = TextUtils.getTable(stringifiedResults, "blue", undefined, undefined, true); -console.log("\n" + resultTable); diff --git a/scripts/performanceTest.js b/scripts/performanceTest.js deleted file mode 100644 index 6925036439..0000000000 --- a/scripts/performanceTest.js +++ /dev/null @@ -1,128 +0,0 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -const childProcess = require("child_process"); -const moment = require("moment"); -const os = require("os"); -const {IO, TextUtils} = require("@brightside/imperative"); -const fs = require("fs"); -const {resolve, join} = require("path"); - -const tempHomeDir = resolve(__dirname + "/../__tests__/__results__/performance"); -const resultFile = tempHomeDir + "/results.txt"; -IO.createDirsSyncFromFilePath(resultFile); -const resultJSONFile = join(tempHomeDir, `results_${moment().format('x')}.json`); -const packageName = "@brightside/core"; -const binName = "bright"; - -const header = `Performance Tests\nCurrent time ${moment()}\nPlatform '${os.platform()}'. Architecture '${os.arch()}'\n` + - `Total Memory: ${os.totalmem()}. Free memory ${os.freemem()}\n` + - `Number of CPUs ${os.cpus().length}.\n` + - `User name: ${os.userInfo().username}\n`; -console.log(header); -IO.writeFile(resultFile, header); - -const results = []; - -/** - * Set the current home directory - */ -const env = JSON.parse(JSON.stringify(process.env)); // copy the current environmental variables -env.ZOWE_CLI_HOME = tempHomeDir; -deleteHomeDirectory(); -uninstallBrightside(); - -/** - * Execute our list of performance test tasks here - */ -results.push(execTimed(`npm install -g ${packageName}@next`, "Install @next version of Brightside")); -results.push(execTimed(`${binName} --help`, `Issue ${binName} --help (no plugins) `)); -results.push(execTimed(`${binName} profiles list zosmf --rfj`, "List zosmf profiles (no plugins) ")); -results.push(execTimed(`${binName} plugins install @brightside/filemasterplus`, "Install filemaster plugin ")); -results.push(execTimed(`${binName} --help`, `Issue ${binName} --help (1 plugin) `)); -results.push(execTimed(`${binName} plugins install @brightside/endevor`, "Install endevor plugin (with filemaster installed) ")); -results.push(execTimed(`${binName} --help`, `Issue ${binName} --help (2 plugins) `)); -results.push(execTimed(`${binName} profiles list zosmf --rfj`, "List zosmf profiles (2 plugins) ")); - -/** - * Get a report of the results - * - * First, add human-readable keys to the result object - */ -const stringifiedResults = results.map(function (result) { - const newResult = JSON.parse(JSON.stringify(result)); // copy the result before modifying - if (newResult.Passed != null) { - newResult.Passed = newResult.Passed ? TextUtils.chalk.green(":)") : TextUtils.chalk.red("X"); - } - newResult["Elapsed Time (ms)"] = newResult.elapsedTime; - newResult.Task = newResult.label; - delete newResult.label; - delete newResult.elapsedTime; - return newResult; -}); -const resultTable = TextUtils.getTable(stringifiedResults, "blue", undefined, undefined, true); -console.log("\n" + resultTable); -IO.writeFile(resultFile, resultTable); -IO.writeFile(resultJSONFile, JSON.stringify({header, results}, null, 2)); - -/** - * Execute a command synchronously and time how long it takes to execute - * @param command - the command to execute - * @param label - label for the action you are performing with this command - * @param expectedTime - the amount of time in milliseconds you expect this command to take - */ -function execTimed(command, label, expectedTime) { - console.log("Running '%s'\n", command); - const beforeTimeStamp = moment(); - const outputFileName = join(tempHomeDir, "output/" + label + ".txt"); - IO.createDirsSyncFromFilePath(outputFileName); - const outputFileStream = fs.openSync(outputFileName, "w+"); - - childProcess.execSync(command, {env, stdio: ["inherit", outputFileStream, outputFileStream]}); - const afterTimeStamp = moment(); - const elapsedTime = afterTimeStamp.diff(beforeTimeStamp); - let timeGreaterThanExpected = undefined; - const result = {label, elapsedTime}; - if (expectedTime != null) { - timeGreaterThanExpected = elapsedTime > expectedTime; - if (timeGreaterThanExpected) { - result.Passed = false; - } else if (timeGreaterThanExpected === false) { - // don't set timeGreaterThanExpected if there's no expected time - result.Passed = true; - } - } - - return result; -} - -/** - * Delete the temporary brightside home directory - */ -function deleteHomeDirectory() { - console.log("Deleting %s...", tempHomeDir); - try { - require("rimraf").sync(tempHomeDir); - } catch (rimrafError) { - throw new Error("Failed to delete " + tempHomeDir + ". Rimraf error:" + rimrafError); - } -} - -function uninstallBrightside() { - console.log("Uninstalling %s before global install\n", packageName); - const outputFileName = join(tempHomeDir, "output/uninstall.txt"); - IO.createDirsSyncFromFilePath(outputFileName); - const outputFileStream = fs.openSync(outputFileName, "w+"); - childProcess.execSync(`npm uninstall -g ${packageName}`, { - env, - stdio: ["inherit", outputFileStream, outputFileStream] - }); -} diff --git a/scripts/updateLicenses.js b/scripts/updateLicenses.js index b5d13c4f60..d50d003171 100644 --- a/scripts/updateLicenses.js +++ b/scripts/updateLicenses.js @@ -35,7 +35,7 @@ require("glob")( alreadyContainedCopyright++; continue; // already has copyright } - const shebangPattern = require("shebang-regex"); + const shebangPattern = /^#!(.*)/; let usedShebang = ""; result = result.replace(shebangPattern, (fullMatch) => { usedShebang = fullMatch + "\n"; // save the shebang that was used, if any diff --git a/typedoc.json b/typedoc.json index a25ecee84c..5f5fff6660 100644 --- a/typedoc.json +++ b/typedoc.json @@ -5,7 +5,7 @@ "**/__tests__/**" ], "cleanOutputDir": true, - "entryPoints": ["./"], + "entryPoints": ["./packages/*"], "entryPointStrategy": "packages", "readme": "./README.md" } \ No newline at end of file diff --git a/zowex/Cargo.lock b/zowex/Cargo.lock index 3a85eec416..301095f6e6 100644 --- a/zowex/Cargo.lock +++ b/zowex/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "anyhow" version = "1.0.69" @@ -27,7 +42,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.12", + "syn 2.0.52", ] [[package]] @@ -36,11 +51,26 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" -version = "0.13.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" [[package]] name = "bitflags" @@ -60,6 +90,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + [[package]] name = "cfg-if" version = "1.0.0" @@ -72,16 +108,6 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" version = "0.8.3" @@ -137,6 +163,12 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + [[package]] name = "hermit-abi" version = "0.2.6" @@ -154,11 +186,11 @@ checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "home" -version = "0.5.4" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -174,9 +206,9 @@ dependencies = [ [[package]] name = "is_ci" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" [[package]] name = "itoa" @@ -208,6 +240,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + [[package]] name = "memoffset" version = "0.8.0" @@ -217,6 +255,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + [[package]] name = "mio" version = "0.8.11" @@ -224,7 +271,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", - "log", "wasi", "windows-sys 0.48.0", ] @@ -248,11 +294,20 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" -version = "1.17.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "pathsearch" @@ -266,33 +321,33 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "proc-macro2" -version = "1.0.52" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "rayon" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" dependencies = [ "either", "rayon-core", @@ -300,14 +355,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -321,14 +374,31 @@ dependencies = [ [[package]] name = "rpassword" -version = "5.0.1" +version = "7.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc936cf8a7ea60c58f030fd36a612a48f440610214dc54bc36431f9ea0c3efb" +checksum = "80472be3c897911d0137b2d2b9055faf6eeac5b14e324073d83bc17b191d7e3f" dependencies = [ "libc", - "winapi", + "rtoolbox", + "windows-sys 0.48.0", +] + +[[package]] +name = "rtoolbox" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c247d24e63230cdb56463ae328478bd5eac8b8faa8c69461a77e8e323afac90e" +dependencies = [ + "libc", + "windows-sys 0.48.0", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "ryu" version = "1.0.13" @@ -343,29 +413,29 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.156" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "314b5b092c0ade17c00142951e50ced110ec27cea304b1037c6969246c2469a4" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.156" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.52", ] [[package]] name = "serde_json" -version = "1.0.94" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -374,27 +444,26 @@ dependencies = [ [[package]] name = "simple-error" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc47a29ce97772ca5c927f75bac34866b16d64e07f330c3248e2d7226623901b" +checksum = "8542b68b8800c3cda649d2c72d688b6907b30f1580043135d61669d4aad1c175" [[package]] name = "socket2" -version = "0.4.9" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "winapi", + "windows-sys 0.52.0", ] [[package]] name = "supports-color" -version = "2.0.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4950e7174bffabe99455511c39707310e7e9b440364a2fcb1cc21521be57b354" +checksum = "9829b314621dfc575df4e409e79f9d6a66a3bd707ab73f23cb4aa3a854ac854f" dependencies = [ - "is-terminal", "is_ci", ] @@ -411,9 +480,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.12" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79d9531f94112cfc3e4c8f5f02cb2b58f72c97b7efd85f70203cc6d8efda5927" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -422,9 +491,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.29.4" +version = "0.30.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "751e810399bba86e9326f5762b7f32ac5a085542df78da6a78d94e07d14d7c11" +checksum = "6746919caf9f2a85bff759535664c060109f21975c5ac2e8652e60102bd4d196" dependencies = [ "cfg-if", "core-foundation-sys", @@ -432,16 +501,16 @@ dependencies = [ "ntapi", "once_cell", "rayon", - "winapi", + "windows", ] [[package]] name = "tokio" -version = "1.28.0" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ - "autocfg", + "backtrace", "bytes", "libc", "mio", @@ -454,13 +523,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.12", + "syn 2.0.52", ] [[package]] @@ -476,9 +545,9 @@ dependencies = [ [[package]] name = "tokio-test" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53474327ae5e166530d17f2d956afcb4f8a004de581b3cae10f12006bc8163e3" +checksum = "e89b3cbabd3ae862100094ae433e1def582cf86451b4e9bf83aa7ac1d8a7d719" dependencies = [ "async-stream", "bytes", @@ -602,6 +671,25 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.4", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -617,7 +705,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.4", ] [[package]] @@ -637,18 +725,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -659,9 +746,9 @@ checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -671,9 +758,9 @@ checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -683,15 +770,9 @@ checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -701,9 +782,9 @@ checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -713,9 +794,9 @@ checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" @@ -725,9 +806,9 @@ checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -737,9 +818,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "yansi" @@ -749,7 +830,7 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" [[package]] name = "zowe" -version = "1.2.2" +version = "1.2.3" dependencies = [ "base64", "fslock", @@ -765,6 +846,6 @@ dependencies = [ "tokio", "tokio-test", "whoami", - "windows-sys 0.48.0", + "windows-sys 0.52.0", "yansi", ] diff --git a/zowex/Cargo.toml b/zowex/Cargo.toml index 33047c8256..973093361e 100644 --- a/zowex/Cargo.toml +++ b/zowex/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zowe" -version = "1.2.2" +version = "1.2.3" authors = ["Zowe Project"] edition = "2018" license = "EPL-2.0" @@ -9,23 +9,23 @@ repository = "https://github.com/zowe/zowe-cli" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -base64 = "0.13.1" -home = "0.5.4" +base64 = "0.22.0" +home = "0.5.9" is-terminal = "0.4.12" pathsearch = "0.2.0" -rpassword = "5.0.1" -serde = { version = "1.0.156", features = ["derive"] } -serde_json = "1.0.94" -simple-error = "0.2.3" -supports-color = "2.0.0" -sysinfo = "0.29.4" -tokio = { version = "1.28.0", features = ["io-util", "macros", "net", "rt-multi-thread"] } +rpassword = "7.3.1" +serde = { version = "1.0.197", features = ["derive"] } +serde_json = "1.0.114" +simple-error = "0.3.0" +supports-color = "3.0.0" +sysinfo = "0.30.6" +tokio = { version = "1.36.0", features = ["io-util", "macros", "net", "rt-multi-thread"] } whoami = "1.5.0" yansi = "0.5.1" [target.'cfg(windows)'.dependencies] fslock = "0.2.1" -windows-sys = "0.48.0" +windows-sys = "0.52.0" [dev-dependencies] -tokio-test = "0.4.2" +tokio-test = "0.4.3" diff --git a/zowex/src/comm.rs b/zowex/src/comm.rs index b884dedba5..415cfc9458 100644 --- a/zowex/src/comm.rs +++ b/zowex/src/comm.rs @@ -9,7 +9,7 @@ * */ -// Functions related to daemon cummunication. +// Functions related to daemon communication. use std::io; use std::io::prelude::*; @@ -26,7 +26,7 @@ use tokio::net::windows::named_pipe::{ClientOptions, NamedPipeClient}; use windows_sys::Win32::Foundation::ERROR_PIPE_BUSY; extern crate base64; -use base64::encode; +use base64::prelude::*; extern crate is_terminal; use is_terminal::IsTerminal; @@ -96,11 +96,11 @@ pub async fn comm_establish_connection( we_started_daemon = true; cmd_to_show = proc_start_daemon(njs_zowe_path); } else if we_started_daemon && conn_retries > THREE_MIN_OF_RETRIES { - println!( + eprintln!( "The Zowe daemon that we started is not running on socket: {}.", daemon_socket ); - println!( + eprintln!( "Command used to start the Zowe daemon was:\n {}\nTerminating.", cmd_to_show ); @@ -115,7 +115,7 @@ pub async fn comm_establish_connection( }; if conn_retries > 0 { - println!( + eprintln!( "{} ({} of {})", retry_msg, conn_retries, THREE_MIN_OF_RETRIES ); @@ -124,7 +124,7 @@ pub async fn comm_establish_connection( conn_retries += 1; if conn_retries > THREE_MIN_OF_RETRIES { - println!( + eprintln!( "Terminating after {} connection retries.", THREE_MIN_OF_RETRIES ); @@ -136,13 +136,13 @@ pub async fn comm_establish_connection( // before we wait too long, show diagnostics if conn_retries == RETRY_TO_SHOW_DIAG { - println!("\nThe Zowe daemon was started with these options:"); + eprintln!("\nThe Zowe daemon was started with these options:"); if we_started_daemon { - println!("Command = {}", cmd_to_show); + eprintln!("Command = {}", cmd_to_show); } else { - println!("Command = {}", daemon_proc_info.cmd); + eprintln!("Command = {}", daemon_proc_info.cmd); } - println!( + eprintln!( "Process name = {} pid = {} socket = {}\n", daemon_proc_info.name, daemon_proc_info.pid, daemon_socket ); @@ -251,7 +251,7 @@ pub async fn comm_talk(message: &[u8], stream: &mut DaemonClient) -> io::Result< env: None, stdinLength: None, stdin: Some(s), - user: Some(encode(executor)), + user: Some(BASE64_STANDARD.encode(executor)), }; let v = serde_json::to_string(&response)?; reader.get_mut().write_all(v.as_bytes()).await?; diff --git a/zowex/src/proc.rs b/zowex/src/proc.rs index 97eb3f4f2a..51eb19f5b0 100644 --- a/zowex/src/proc.rs +++ b/zowex/src/proc.rs @@ -20,7 +20,7 @@ use std::process::{Command, Stdio}; use std::os::windows::process::CommandExt; extern crate sysinfo; -use sysinfo::{Pid, PidExt, ProcessExt, System, SystemExt}; +use sysinfo::{Pid, System}; extern crate simple_error; use simple_error::SimpleError; @@ -196,7 +196,7 @@ fn read_pid_for_user() -> Option { Ok(ok_val) => ok_val, Err(err_val) => { // we should not continue if we cannot open an existing pid file - println!( + eprintln!( "Unable to open file = {}\nDetails = {}", pid_file_path.display(), err_val @@ -209,7 +209,7 @@ fn read_pid_for_user() -> Option { Ok(ok_val) => ok_val, Err(err_val) => { // we should not continue if we cannot read an existing pid file - println!( + eprintln!( "Unable to read file = {}\nDetails = {}", pid_file_path.display(), err_val @@ -222,7 +222,7 @@ fn read_pid_for_user() -> Option { if daemon_pid_for_user.user != executor { // our pid file should only contain our own user name - println!( + eprintln!( "User name of '{}' in file '{}' does not match current user = '{}'.", daemon_pid_for_user.user, pid_file_path.display(), @@ -273,11 +273,11 @@ fn read_pid_for_user() -> Option { */ pub fn proc_start_daemon(njs_zowe_path: &str) -> String { - println!("Starting a background process to increase performance ..."); + eprintln!("Starting a background process to increase performance ..."); let daemon_arg = LAUNCH_DAEMON_OPTION; let mut cmd = Command::new(njs_zowe_path); - + // Uses creation flags from https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags // Flags are CREATE_NO_WINDOW, CREATE_NEW_PROCESS_GROUP, and CREATE_UNICODE_ENVIRONMENT #[cfg(target_family = "windows")] @@ -291,11 +291,11 @@ pub fn proc_start_daemon(njs_zowe_path: &str) -> String { { Ok(_unused) => { /* nothing to do */ } Err(error) => { - println!( + eprintln!( "Failed to start the following process:\n {} {}", njs_zowe_path, daemon_arg ); - println!("Due to this error:\n {}", error); + eprintln!("Due to this error:\n {}", error); std::process::exit(EXIT_CODE_CANNOT_START_DAEMON); } }; diff --git a/zowex/src/run.rs b/zowex/src/run.rs index 191e634082..2d5ff8f077 100644 --- a/zowex/src/run.rs +++ b/zowex/src/run.rs @@ -21,7 +21,7 @@ use std::process::{Command, Stdio}; use std::thread; use std::time::Duration; -use base64::encode; +use base64::prelude::*; use is_terminal::IsTerminal; #[cfg(target_family = "windows")] @@ -96,17 +96,17 @@ pub async fn run_zowe_command(zowe_cmd_args: &mut Vec) -> Result Result { if proc_get_daemon_info().is_running { - println!("Shutting down the running daemon ..."); + eprintln!("Shutting down the running daemon ..."); let mut restart_cmd_args: Vec = vec![SHUTDOWN_REQUEST.to_string()]; if let Err(err_val) = run_daemon_command(njs_zowe_path, &mut restart_cmd_args).await { - println!("Unable to communicate a command to the Zowe daemon."); + eprintln!("Unable to communicate a command to the Zowe daemon."); return Err(err_val); } } // Start a new daemon. Note that proc_start_daemon() exits on failure. proc_start_daemon(njs_zowe_path); - println!("A new daemon has started."); + eprintln!("A new daemon has started."); Ok(EXIT_CODE_SUCCESS) } @@ -134,12 +134,12 @@ fn run_nodejs_command(njs_zowe_path: &str, zowe_cmd_args: &mut Vec) -> R { Ok(new_proc) => new_proc.status.code().unwrap(), Err(error) => { - println!("Failed to run the following command:"); - println!( + eprintln!("Failed to run the following command:"); + eprintln!( " Program = {}\n arguments = {:?}", njs_zowe_path, zowe_cmd_args ); - println!("Due to this error:\n {}", error); + eprintln!("Due to this error:\n {}", error); EXIT_CODE_FAILED_TO_RUN_NODEJS_CMD } }; @@ -177,12 +177,12 @@ fn run_delayed_zowe_command(njs_zowe_path: &str, zowe_cmd_args: &[String]) -> Re let (curr_cmd_shell, cmd_shell_nm) = match proc_get_cmd_shell() { Ok((curr_cmd_shell, cmd_shell_nm)) => (curr_cmd_shell, cmd_shell_nm), Err(error) => { - println!("{} Terminating.", error); + eprintln!("{} Terminating.", error); return Err(EXIT_CODE_CANT_FIND_CMD_SHELL); } }; if matches!(curr_cmd_shell, CmdShell::Unknown) { - println!( + eprintln!( "The command shell process named '{}' is unknown to the Zowe CLI. Terminating.", cmd_shell_nm ); @@ -205,9 +205,9 @@ fn run_delayed_zowe_command(njs_zowe_path: &str, zowe_cmd_args: &[String]) -> Re ); // The following line gives useful debugging info when it is uncommented. - // println!("script_arg_vec = {:?}", script_arg_vec); + // eprintln!("script_arg_vec = {:?}", script_arg_vec); - println!( + eprintln!( "The '{}' command will run in the background ...", arg_vec_to_string(zowe_cmd_args) ); @@ -220,12 +220,12 @@ fn run_delayed_zowe_command(njs_zowe_path: &str, zowe_cmd_args: &[String]) -> Re { Ok(..) => Ok(EXIT_CODE_SUCCESS), Err(err_val) => { - println!("Failed to run the following command:"); - println!( + eprintln!("Failed to run the following command:"); + eprintln!( " cmd_shell_to_launch = {}\n arguments = {:?}", njs_zowe_path, zowe_cmd_args ); - println!("Due to this error:\n {}", err_val); + eprintln!("Due to this error:\n {}", err_val); Err(EXIT_CODE_FAILED_TO_RUN_NODEJS_CMD) } }; @@ -252,7 +252,7 @@ pub async fn run_daemon_command( let cwd: PathBuf = match env::current_dir() { Ok(ok_val) => ok_val, Err(err_val) => { - println!("Unable to get current directory\nDetails = {:?}", err_val); + eprintln!("Unable to get current directory\nDetails = {:?}", err_val); return Err(EXIT_CODE_ENV_ERROR); } }; @@ -260,7 +260,7 @@ pub async fn run_daemon_command( let mut stdin = Vec::new(); if !std::io::stdin().is_terminal() { if let Err(err_val) = io::stdin().read_to_end(&mut stdin) { - println!("Failed reading stdin\nDetails = {}", err_val); + eprintln!("Failed reading stdin\nDetails = {}", err_val); return Err(EXIT_CODE_COMM_IO_ERROR); } } @@ -278,7 +278,7 @@ pub async fn run_daemon_command( env: None, stdinLength: Some(0), stdin: Some(control_c), - user: Some(encode(executor)), + user: Some(BASE64_STANDARD.encode(executor)), } } else { DaemonResponse { @@ -287,7 +287,7 @@ pub async fn run_daemon_command( env: Some(util_get_zowe_env()), stdinLength: Some(stdin.len() as i32), stdin: None, - user: Some(encode(executor)), + user: Some(BASE64_STANDARD.encode(executor)), } }; @@ -301,7 +301,7 @@ pub async fn run_daemon_command( } } Err(err_val) => { - println!("Failed convert response to JSON\nDetails = {}", err_val); + eprintln!("Failed to convert response to JSON\nDetails = {}", err_val); return Err(EXIT_CODE_CANT_CONVERT_JSON); } } @@ -323,7 +323,7 @@ pub async fn run_daemon_command( match lock_file.try_lock() { Ok(result) if !result => { if tries > THREE_MIN_OF_RETRIES { - println!( + eprintln!( "Terminating after {} connection retries.", THREE_MIN_OF_RETRIES ); @@ -331,7 +331,7 @@ pub async fn run_daemon_command( } tries += 1; - println!( + eprintln!( "The Zowe daemon is in use, retrying ({} of {})", tries, THREE_MIN_OF_RETRIES ); @@ -344,7 +344,7 @@ pub async fn run_daemon_command( locked = true; } Err(ref e) => { - println!("Problem acquiring lock: {:?}", e); + eprintln!("Problem acquiring lock: {:?}", e); return Err(EXIT_CODE_CANNOT_ACQUIRE_LOCK); } } @@ -354,7 +354,7 @@ pub async fn run_daemon_command( match comm_establish_connection(njs_zowe_path, &socket_string).await { Ok(ok_val) => stream = ok_val, Err(err_val) => { - println!( + eprintln!( "Unable to establish communication with daemon.\nDetails = {}", err_val ); @@ -369,7 +369,7 @@ pub async fn run_daemon_command( Err(ref err_val) => { if err_val.kind() == io::ErrorKind::ConnectionReset { if tries > THREE_MIN_OF_RETRIES { - println!( + eprintln!( "Terminating after {} connection retries.", THREE_MIN_OF_RETRIES ); @@ -377,7 +377,7 @@ pub async fn run_daemon_command( } tries += 1; - println!( + eprintln!( "The Zowe daemon is in use, retrying ({} of {})", tries, THREE_MIN_OF_RETRIES ); @@ -385,7 +385,7 @@ pub async fn run_daemon_command( // pause between attempts to connect thread::sleep(Duration::from_secs(THREE_SEC_DELAY)); } else { - println!( + eprintln!( "I/O error during daemon communication.\nDetails = {}", err_val ); @@ -648,21 +648,21 @@ fn get_win_lock_file() -> Result { lock_path.push("daemon.lock"); if let Err(err_val) = File::create(&lock_path) { - println!( + eprintln!( "Unable to create zowe daemon lock file = {}.", &lock_path.display() ); - println!("Reason = {}.", err_val); + eprintln!("Reason = {}.", err_val); return Err(EXIT_CODE_FILE_IO_ERROR); } let lock_file: LockFile = match LockFile::open(&lock_path) { Ok(ok_val) => ok_val, Err(err_val) => { - println!( + eprintln!( "Unable to open zowe daemon lock file = {}.", &lock_path.display() ); - println!("Reason = {}.", err_val); + eprintln!("Reason = {}.", err_val); return Err(EXIT_CODE_FILE_IO_ERROR); } }; diff --git a/zowex/src/util.rs b/zowex/src/util.rs index fb607309d9..53cbe1ef31 100644 --- a/zowex/src/util.rs +++ b/zowex/src/util.rs @@ -44,7 +44,7 @@ pub fn util_get_nodejs_zowe_path() -> String { */ let my_exe_result = env::current_exe(); if my_exe_result.is_err() { - println!("Unable to get path to my own executable. Terminating."); + eprintln!("Unable to get path to my own executable. Terminating."); std::process::exit(EXIT_CODE_CANNOT_GET_MY_PATH); } let my_exe_path_buf = my_exe_result.unwrap(); @@ -73,8 +73,8 @@ pub fn util_get_nodejs_zowe_path() -> String { break; } if njs_zowe_path == NOT_FOUND { - println!("Could not find a NodeJS zowe command on your path."); - println!("Will not be able to run Zowe commands. Terminating."); + eprintln!("Could not find a NodeJS zowe command on your path."); + eprintln!("Will not be able to run Zowe commands. Terminating."); std::process::exit(EXIT_CODE_NO_NODEJS_ZOWE_ON_PATH); } @@ -96,7 +96,7 @@ pub fn util_get_daemon_dir() -> Result { match home_dir() { Some(path_buf_val) => daemon_dir = path_buf_val, None => { - println!("Unable to get user's home directory."); + eprintln!("Unable to get user's home directory."); return Err(EXIT_CODE_ENV_ERROR); } } @@ -106,11 +106,11 @@ pub fn util_get_daemon_dir() -> Result { if !daemon_dir.exists() { if let Err(err_val) = std::fs::create_dir_all(&daemon_dir) { - println!( + eprintln!( "Unable to create zowe daemon directory = {}.", &daemon_dir.display() ); - println!("Reason = {}.", err_val); + eprintln!("Reason = {}.", err_val); return Err(EXIT_CODE_FILE_IO_ERROR); } } @@ -178,6 +178,6 @@ pub fn util_terminal_supports_color() -> i32 { return 1; } } - + 0 } \ No newline at end of file